mirror of
https://github.com/esphome/esphome.git
synced 2024-12-20 12:34:54 +01:00
[qspi_dbi] Bugfix and new features (#7979)
This commit is contained in:
parent
265b6ec445
commit
ac631711ab
6 changed files with 339 additions and 69 deletions
|
@ -23,7 +23,7 @@ from esphome.helpers import write_file_if_changed
|
||||||
|
|
||||||
from . import defines as df, helpers, lv_validation as lvalid
|
from . import defines as df, helpers, lv_validation as lvalid
|
||||||
from .automation import disp_update, focused_widgets, update_to_code
|
from .automation import disp_update, focused_widgets, update_to_code
|
||||||
from .defines import add_define
|
from .defines import CONF_DRAW_ROUNDING, add_define
|
||||||
from .encoders import (
|
from .encoders import (
|
||||||
ENCODERS_CONFIG,
|
ENCODERS_CONFIG,
|
||||||
encoders_to_code,
|
encoders_to_code,
|
||||||
|
@ -205,6 +205,10 @@ def final_validation(configs):
|
||||||
raise cv.Invalid(
|
raise cv.Invalid(
|
||||||
"Using auto_clear_enabled: true in display config not compatible with LVGL"
|
"Using auto_clear_enabled: true in display config not compatible with LVGL"
|
||||||
)
|
)
|
||||||
|
if draw_rounding := display.get(CONF_DRAW_ROUNDING):
|
||||||
|
config[CONF_DRAW_ROUNDING] = max(
|
||||||
|
draw_rounding, config[CONF_DRAW_ROUNDING]
|
||||||
|
)
|
||||||
buffer_frac = config[CONF_BUFFER_SIZE]
|
buffer_frac = config[CONF_BUFFER_SIZE]
|
||||||
if CORE.is_esp32 and buffer_frac > 0.5 and "psram" not in global_config:
|
if CORE.is_esp32 and buffer_frac > 0.5 and "psram" not in global_config:
|
||||||
LOGGER.warning("buffer_size: may need to be reduced without PSRAM")
|
LOGGER.warning("buffer_size: may need to be reduced without PSRAM")
|
||||||
|
|
|
@ -1 +1,4 @@
|
||||||
CODEOWNERS = ["@clydebarrow"]
|
CODEOWNERS = ["@clydebarrow"]
|
||||||
|
|
||||||
|
CONF_DRAW_FROM_ORIGIN = "draw_from_origin"
|
||||||
|
CONF_DRAW_ROUNDING = "draw_rounding"
|
||||||
|
|
|
@ -24,6 +24,7 @@ from esphome.const import (
|
||||||
)
|
)
|
||||||
from esphome.core import TimePeriod
|
from esphome.core import TimePeriod
|
||||||
|
|
||||||
|
from . import CONF_DRAW_FROM_ORIGIN, CONF_DRAW_ROUNDING
|
||||||
from .models import DriverChip
|
from .models import DriverChip
|
||||||
|
|
||||||
DEPENDENCIES = ["spi"]
|
DEPENDENCIES = ["spi"]
|
||||||
|
@ -41,7 +42,6 @@ COLOR_ORDERS = {
|
||||||
}
|
}
|
||||||
DATA_PIN_SCHEMA = pins.internal_gpio_output_pin_schema
|
DATA_PIN_SCHEMA = pins.internal_gpio_output_pin_schema
|
||||||
|
|
||||||
CONF_DRAW_FROM_ORIGIN = "draw_from_origin"
|
|
||||||
DELAY_FLAG = 0xFF
|
DELAY_FLAG = 0xFF
|
||||||
|
|
||||||
|
|
||||||
|
@ -78,14 +78,17 @@ def _validate(config):
|
||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
CONFIG_SCHEMA = cv.All(
|
def power_of_two(value):
|
||||||
display.FULL_DISPLAY_SCHEMA.extend(
|
value = cv.int_range(1, 128)(value)
|
||||||
|
if value & (value - 1) != 0:
|
||||||
|
raise cv.Invalid("value must be a power of two")
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
|
BASE_SCHEMA = display.FULL_DISPLAY_SCHEMA.extend(
|
||||||
cv.Schema(
|
cv.Schema(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(QSPI_DBI),
|
cv.GenerateID(): cv.declare_id(QSPI_DBI),
|
||||||
cv.Required(CONF_MODEL): cv.one_of(
|
|
||||||
*DriverChip.chips.keys(), upper=True
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_INIT_SEQUENCE): cv.ensure_list(map_sequence),
|
cv.Optional(CONF_INIT_SEQUENCE): cv.ensure_list(map_sequence),
|
||||||
cv.Required(CONF_DIMENSIONS): cv.Any(
|
cv.Required(CONF_DIMENSIONS): cv.Any(
|
||||||
cv.dimensions,
|
cv.dimensions,
|
||||||
|
@ -93,32 +96,17 @@ CONFIG_SCHEMA = cv.All(
|
||||||
{
|
{
|
||||||
cv.Required(CONF_WIDTH): validate_dimension,
|
cv.Required(CONF_WIDTH): validate_dimension,
|
||||||
cv.Required(CONF_HEIGHT): validate_dimension,
|
cv.Required(CONF_HEIGHT): validate_dimension,
|
||||||
cv.Optional(
|
cv.Optional(CONF_OFFSET_HEIGHT, default=0): validate_dimension,
|
||||||
CONF_OFFSET_HEIGHT, default=0
|
cv.Optional(CONF_OFFSET_WIDTH, default=0): validate_dimension,
|
||||||
): validate_dimension,
|
|
||||||
cv.Optional(
|
|
||||||
CONF_OFFSET_WIDTH, default=0
|
|
||||||
): validate_dimension,
|
|
||||||
}
|
}
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_TRANSFORM): cv.Schema(
|
cv.Optional(CONF_DRAW_FROM_ORIGIN, default=False): cv.boolean,
|
||||||
{
|
|
||||||
cv.Optional(CONF_MIRROR_X, default=False): cv.boolean,
|
|
||||||
cv.Optional(CONF_MIRROR_Y, default=False): cv.boolean,
|
|
||||||
cv.Optional(CONF_SWAP_XY, default=False): cv.boolean,
|
|
||||||
}
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_COLOR_ORDER, default="RGB"): cv.enum(
|
|
||||||
COLOR_ORDERS, upper=True
|
|
||||||
),
|
|
||||||
cv.Optional(CONF_INVERT_COLORS, default=False): cv.boolean,
|
|
||||||
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
cv.Optional(CONF_RESET_PIN): pins.gpio_output_pin_schema,
|
||||||
cv.Optional(CONF_ENABLE_PIN): pins.gpio_output_pin_schema,
|
cv.Optional(CONF_ENABLE_PIN): pins.gpio_output_pin_schema,
|
||||||
cv.Optional(CONF_BRIGHTNESS, default=0xD0): cv.int_range(
|
cv.Optional(CONF_BRIGHTNESS, default=0xD0): cv.int_range(
|
||||||
0, 0xFF, min_included=True, max_included=True
|
0, 0xFF, min_included=True, max_included=True
|
||||||
),
|
),
|
||||||
cv.Optional(CONF_DRAW_FROM_ORIGIN, default=False): cv.boolean,
|
|
||||||
}
|
}
|
||||||
).extend(
|
).extend(
|
||||||
spi.spi_device_schema(
|
spi.spi_device_schema(
|
||||||
|
@ -128,6 +116,43 @@ CONFIG_SCHEMA = cv.All(
|
||||||
quad=True,
|
quad=True,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def model_property(name, defaults, fallback):
|
||||||
|
return cv.Optional(name, default=defaults.get(name, fallback))
|
||||||
|
|
||||||
|
|
||||||
|
def model_schema(defaults):
|
||||||
|
transform = cv.Schema(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_MIRROR_X, default=False): cv.boolean,
|
||||||
|
cv.Optional(CONF_MIRROR_Y, default=False): cv.boolean,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
if defaults.get(CONF_SWAP_XY, True):
|
||||||
|
transform = transform.extend(
|
||||||
|
{
|
||||||
|
cv.Optional(CONF_SWAP_XY, default=False): cv.boolean,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
return BASE_SCHEMA.extend(
|
||||||
|
{
|
||||||
|
model_property(CONF_INVERT_COLORS, defaults, False): cv.boolean,
|
||||||
|
model_property(CONF_COLOR_ORDER, defaults, "RGB"): cv.enum(
|
||||||
|
COLOR_ORDERS, upper=True
|
||||||
|
),
|
||||||
|
model_property(CONF_DRAW_ROUNDING, defaults, 2): power_of_two,
|
||||||
|
cv.Optional(CONF_TRANSFORM): transform,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
CONFIG_SCHEMA = cv.All(
|
||||||
|
cv.typed_schema(
|
||||||
|
{k.upper(): model_schema(v.defaults) for k, v in DriverChip.chips.items()},
|
||||||
|
upper=True,
|
||||||
|
key=CONF_MODEL,
|
||||||
),
|
),
|
||||||
cv.only_with_esp_idf,
|
cv.only_with_esp_idf,
|
||||||
)
|
)
|
||||||
|
@ -152,6 +177,7 @@ async def to_code(config):
|
||||||
cg.add(var.set_brightness(config[CONF_BRIGHTNESS]))
|
cg.add(var.set_brightness(config[CONF_BRIGHTNESS]))
|
||||||
cg.add(var.set_model(config[CONF_MODEL]))
|
cg.add(var.set_model(config[CONF_MODEL]))
|
||||||
cg.add(var.set_draw_from_origin(config[CONF_DRAW_FROM_ORIGIN]))
|
cg.add(var.set_draw_from_origin(config[CONF_DRAW_FROM_ORIGIN]))
|
||||||
|
cg.add(var.set_draw_rounding(config[CONF_DRAW_ROUNDING]))
|
||||||
if enable_pin := config.get(CONF_ENABLE_PIN):
|
if enable_pin := config.get(CONF_ENABLE_PIN):
|
||||||
enable = await cg.gpio_pin_expression(enable_pin)
|
enable = await cg.gpio_pin_expression(enable_pin)
|
||||||
cg.add(var.set_enable_pin(enable))
|
cg.add(var.set_enable_pin(enable))
|
||||||
|
@ -163,7 +189,8 @@ async def to_code(config):
|
||||||
if transform := config.get(CONF_TRANSFORM):
|
if transform := config.get(CONF_TRANSFORM):
|
||||||
cg.add(var.set_mirror_x(transform[CONF_MIRROR_X]))
|
cg.add(var.set_mirror_x(transform[CONF_MIRROR_X]))
|
||||||
cg.add(var.set_mirror_y(transform[CONF_MIRROR_Y]))
|
cg.add(var.set_mirror_y(transform[CONF_MIRROR_Y]))
|
||||||
cg.add(var.set_swap_xy(transform[CONF_SWAP_XY]))
|
# swap_xy is not implemented for some chips
|
||||||
|
cg.add(var.set_swap_xy(transform.get(CONF_SWAP_XY, False)))
|
||||||
|
|
||||||
if CONF_DIMENSIONS in config:
|
if CONF_DIMENSIONS in config:
|
||||||
dimensions = config[CONF_DIMENSIONS]
|
dimensions = config[CONF_DIMENSIONS]
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
# Commands
|
# Commands
|
||||||
|
from esphome.const import CONF_INVERT_COLORS, CONF_SWAP_XY
|
||||||
|
|
||||||
|
from . import CONF_DRAW_ROUNDING
|
||||||
|
|
||||||
SW_RESET_CMD = 0x01
|
SW_RESET_CMD = 0x01
|
||||||
|
SLEEP_IN = 0x10
|
||||||
SLEEP_OUT = 0x11
|
SLEEP_OUT = 0x11
|
||||||
NORON = 0x13
|
NORON = 0x13
|
||||||
INVERT_OFF = 0x20
|
INVERT_OFF = 0x20
|
||||||
|
@ -24,11 +29,12 @@ PAGESEL = 0xFE
|
||||||
class DriverChip:
|
class DriverChip:
|
||||||
chips = {}
|
chips = {}
|
||||||
|
|
||||||
def __init__(self, name: str):
|
def __init__(self, name: str, defaults=None):
|
||||||
name = name.upper()
|
name = name.upper()
|
||||||
self.name = name
|
self.name = name
|
||||||
self.chips[name] = self
|
self.chips[name] = self
|
||||||
self.initsequence = []
|
self.initsequence = []
|
||||||
|
self.defaults = defaults or {}
|
||||||
|
|
||||||
def cmd(self, c, *args):
|
def cmd(self, c, *args):
|
||||||
"""
|
"""
|
||||||
|
@ -59,9 +65,246 @@ chip.cmd(TEON, 0x00)
|
||||||
chip.cmd(PIXFMT, 0x55)
|
chip.cmd(PIXFMT, 0x55)
|
||||||
chip.cmd(NORON)
|
chip.cmd(NORON)
|
||||||
|
|
||||||
chip = DriverChip("AXS15231")
|
chip = DriverChip("AXS15231", {CONF_DRAW_ROUNDING: 8, CONF_SWAP_XY: False})
|
||||||
chip.cmd(0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xA5)
|
chip.cmd(0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xA5)
|
||||||
chip.cmd(0xC1, 0x33)
|
chip.cmd(0xC1, 0x33)
|
||||||
chip.cmd(0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
|
chip.cmd(0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
|
||||||
|
|
||||||
|
chip = DriverChip(
|
||||||
|
"JC4832W535",
|
||||||
|
{
|
||||||
|
CONF_DRAW_ROUNDING: 8,
|
||||||
|
CONF_SWAP_XY: False,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
chip.cmd(DISPLAY_OFF)
|
||||||
|
chip.delay(20)
|
||||||
|
chip.cmd(SLEEP_IN)
|
||||||
|
chip.delay(80)
|
||||||
|
chip.cmd(SLEEP_OUT)
|
||||||
|
chip.cmd(INVERT_OFF)
|
||||||
|
# A magic sequence to enable the windowed drawing mode
|
||||||
|
chip.cmd(0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xA5)
|
||||||
|
chip.cmd(0xC1, 0x33)
|
||||||
|
chip.cmd(0xBB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00)
|
||||||
|
|
||||||
|
chip = DriverChip("JC3636W518", {CONF_INVERT_COLORS: True})
|
||||||
|
chip.cmd(0xF0, 0x08)
|
||||||
|
chip.cmd(0xF2, 0x08)
|
||||||
|
chip.cmd(0x9B, 0x51)
|
||||||
|
chip.cmd(0x86, 0x53)
|
||||||
|
chip.cmd(0xF2, 0x80)
|
||||||
|
chip.cmd(0xF0, 0x00)
|
||||||
|
chip.cmd(0xF0, 0x01)
|
||||||
|
chip.cmd(0xF1, 0x01)
|
||||||
|
chip.cmd(0xB0, 0x54)
|
||||||
|
chip.cmd(0xB1, 0x3F)
|
||||||
|
chip.cmd(0xB2, 0x2A)
|
||||||
|
chip.cmd(0xB4, 0x46)
|
||||||
|
chip.cmd(0xB5, 0x34)
|
||||||
|
chip.cmd(0xB6, 0xD5)
|
||||||
|
chip.cmd(0xB7, 0x30)
|
||||||
|
chip.cmd(0xBA, 0x00)
|
||||||
|
chip.cmd(0xBB, 0x08)
|
||||||
|
chip.cmd(0xBC, 0x08)
|
||||||
|
chip.cmd(0xBD, 0x00)
|
||||||
|
chip.cmd(0xC0, 0x80)
|
||||||
|
chip.cmd(0xC1, 0x10)
|
||||||
|
chip.cmd(0xC2, 0x37)
|
||||||
|
chip.cmd(0xC3, 0x80)
|
||||||
|
chip.cmd(0xC4, 0x10)
|
||||||
|
chip.cmd(0xC5, 0x37)
|
||||||
|
chip.cmd(0xC6, 0xA9)
|
||||||
|
chip.cmd(0xC7, 0x41)
|
||||||
|
chip.cmd(0xC8, 0x51)
|
||||||
|
chip.cmd(0xC9, 0xA9)
|
||||||
|
chip.cmd(0xCA, 0x41)
|
||||||
|
chip.cmd(0xCB, 0x51)
|
||||||
|
chip.cmd(0xD0, 0x91)
|
||||||
|
chip.cmd(0xD1, 0x68)
|
||||||
|
chip.cmd(0xD2, 0x69)
|
||||||
|
chip.cmd(0xF5, 0x00, 0xA5)
|
||||||
|
chip.cmd(0xDD, 0x3F)
|
||||||
|
chip.cmd(0xDE, 0x3F)
|
||||||
|
chip.cmd(0xF1, 0x10)
|
||||||
|
chip.cmd(0xF0, 0x00)
|
||||||
|
chip.cmd(0xF0, 0x02)
|
||||||
|
chip.cmd(
|
||||||
|
0xE0,
|
||||||
|
0x70,
|
||||||
|
0x09,
|
||||||
|
0x12,
|
||||||
|
0x0C,
|
||||||
|
0x0B,
|
||||||
|
0x27,
|
||||||
|
0x38,
|
||||||
|
0x54,
|
||||||
|
0x4E,
|
||||||
|
0x19,
|
||||||
|
0x15,
|
||||||
|
0x15,
|
||||||
|
0x2C,
|
||||||
|
0x2F,
|
||||||
|
)
|
||||||
|
chip.cmd(
|
||||||
|
0xE1,
|
||||||
|
0x70,
|
||||||
|
0x08,
|
||||||
|
0x11,
|
||||||
|
0x0C,
|
||||||
|
0x0B,
|
||||||
|
0x27,
|
||||||
|
0x38,
|
||||||
|
0x43,
|
||||||
|
0x4C,
|
||||||
|
0x18,
|
||||||
|
0x14,
|
||||||
|
0x14,
|
||||||
|
0x2B,
|
||||||
|
0x2D,
|
||||||
|
)
|
||||||
|
chip.cmd(0xF0, 0x10)
|
||||||
|
chip.cmd(0xF3, 0x10)
|
||||||
|
chip.cmd(0xE0, 0x08)
|
||||||
|
chip.cmd(0xE1, 0x00)
|
||||||
|
chip.cmd(0xE2, 0x00)
|
||||||
|
chip.cmd(0xE3, 0x00)
|
||||||
|
chip.cmd(0xE4, 0xE0)
|
||||||
|
chip.cmd(0xE5, 0x06)
|
||||||
|
chip.cmd(0xE6, 0x21)
|
||||||
|
chip.cmd(0xE7, 0x00)
|
||||||
|
chip.cmd(0xE8, 0x05)
|
||||||
|
chip.cmd(0xE9, 0x82)
|
||||||
|
chip.cmd(0xEA, 0xDF)
|
||||||
|
chip.cmd(0xEB, 0x89)
|
||||||
|
chip.cmd(0xEC, 0x20)
|
||||||
|
chip.cmd(0xED, 0x14)
|
||||||
|
chip.cmd(0xEE, 0xFF)
|
||||||
|
chip.cmd(0xEF, 0x00)
|
||||||
|
chip.cmd(0xF8, 0xFF)
|
||||||
|
chip.cmd(0xF9, 0x00)
|
||||||
|
chip.cmd(0xFA, 0x00)
|
||||||
|
chip.cmd(0xFB, 0x30)
|
||||||
|
chip.cmd(0xFC, 0x00)
|
||||||
|
chip.cmd(0xFD, 0x00)
|
||||||
|
chip.cmd(0xFE, 0x00)
|
||||||
|
chip.cmd(0xFF, 0x00)
|
||||||
|
chip.cmd(0x60, 0x42)
|
||||||
|
chip.cmd(0x61, 0xE0)
|
||||||
|
chip.cmd(0x62, 0x40)
|
||||||
|
chip.cmd(0x63, 0x40)
|
||||||
|
chip.cmd(0x64, 0x02)
|
||||||
|
chip.cmd(0x65, 0x00)
|
||||||
|
chip.cmd(0x66, 0x40)
|
||||||
|
chip.cmd(0x67, 0x03)
|
||||||
|
chip.cmd(0x68, 0x00)
|
||||||
|
chip.cmd(0x69, 0x00)
|
||||||
|
chip.cmd(0x6A, 0x00)
|
||||||
|
chip.cmd(0x6B, 0x00)
|
||||||
|
chip.cmd(0x70, 0x42)
|
||||||
|
chip.cmd(0x71, 0xE0)
|
||||||
|
chip.cmd(0x72, 0x40)
|
||||||
|
chip.cmd(0x73, 0x40)
|
||||||
|
chip.cmd(0x74, 0x02)
|
||||||
|
chip.cmd(0x75, 0x00)
|
||||||
|
chip.cmd(0x76, 0x40)
|
||||||
|
chip.cmd(0x77, 0x03)
|
||||||
|
chip.cmd(0x78, 0x00)
|
||||||
|
chip.cmd(0x79, 0x00)
|
||||||
|
chip.cmd(0x7A, 0x00)
|
||||||
|
chip.cmd(0x7B, 0x00)
|
||||||
|
chip.cmd(0x80, 0x48)
|
||||||
|
chip.cmd(0x81, 0x00)
|
||||||
|
chip.cmd(0x82, 0x05)
|
||||||
|
chip.cmd(0x83, 0x02)
|
||||||
|
chip.cmd(0x84, 0xDD)
|
||||||
|
chip.cmd(0x85, 0x00)
|
||||||
|
chip.cmd(0x86, 0x00)
|
||||||
|
chip.cmd(0x87, 0x00)
|
||||||
|
chip.cmd(0x88, 0x48)
|
||||||
|
chip.cmd(0x89, 0x00)
|
||||||
|
chip.cmd(0x8A, 0x07)
|
||||||
|
chip.cmd(0x8B, 0x02)
|
||||||
|
chip.cmd(0x8C, 0xDF)
|
||||||
|
chip.cmd(0x8D, 0x00)
|
||||||
|
chip.cmd(0x8E, 0x00)
|
||||||
|
chip.cmd(0x8F, 0x00)
|
||||||
|
chip.cmd(0x90, 0x48)
|
||||||
|
chip.cmd(0x91, 0x00)
|
||||||
|
chip.cmd(0x92, 0x09)
|
||||||
|
chip.cmd(0x93, 0x02)
|
||||||
|
chip.cmd(0x94, 0xE1)
|
||||||
|
chip.cmd(0x95, 0x00)
|
||||||
|
chip.cmd(0x96, 0x00)
|
||||||
|
chip.cmd(0x97, 0x00)
|
||||||
|
chip.cmd(0x98, 0x48)
|
||||||
|
chip.cmd(0x99, 0x00)
|
||||||
|
chip.cmd(0x9A, 0x0B)
|
||||||
|
chip.cmd(0x9B, 0x02)
|
||||||
|
chip.cmd(0x9C, 0xE3)
|
||||||
|
chip.cmd(0x9D, 0x00)
|
||||||
|
chip.cmd(0x9E, 0x00)
|
||||||
|
chip.cmd(0x9F, 0x00)
|
||||||
|
chip.cmd(0xA0, 0x48)
|
||||||
|
chip.cmd(0xA1, 0x00)
|
||||||
|
chip.cmd(0xA2, 0x04)
|
||||||
|
chip.cmd(0xA3, 0x02)
|
||||||
|
chip.cmd(0xA4, 0xDC)
|
||||||
|
chip.cmd(0xA5, 0x00)
|
||||||
|
chip.cmd(0xA6, 0x00)
|
||||||
|
chip.cmd(0xA7, 0x00)
|
||||||
|
chip.cmd(0xA8, 0x48)
|
||||||
|
chip.cmd(0xA9, 0x00)
|
||||||
|
chip.cmd(0xAA, 0x06)
|
||||||
|
chip.cmd(0xAB, 0x02)
|
||||||
|
chip.cmd(0xAC, 0xDE)
|
||||||
|
chip.cmd(0xAD, 0x00)
|
||||||
|
chip.cmd(0xAE, 0x00)
|
||||||
|
chip.cmd(0xAF, 0x00)
|
||||||
|
chip.cmd(0xB0, 0x48)
|
||||||
|
chip.cmd(0xB1, 0x00)
|
||||||
|
chip.cmd(0xB2, 0x08)
|
||||||
|
chip.cmd(0xB3, 0x02)
|
||||||
|
chip.cmd(0xB4, 0xE0)
|
||||||
|
chip.cmd(0xB5, 0x00)
|
||||||
|
chip.cmd(0xB6, 0x00)
|
||||||
|
chip.cmd(0xB7, 0x00)
|
||||||
|
chip.cmd(0xB8, 0x48)
|
||||||
|
chip.cmd(0xB9, 0x00)
|
||||||
|
chip.cmd(0xBA, 0x0A)
|
||||||
|
chip.cmd(0xBB, 0x02)
|
||||||
|
chip.cmd(0xBC, 0xE2)
|
||||||
|
chip.cmd(0xBD, 0x00)
|
||||||
|
chip.cmd(0xBE, 0x00)
|
||||||
|
chip.cmd(0xBF, 0x00)
|
||||||
|
chip.cmd(0xC0, 0x12)
|
||||||
|
chip.cmd(0xC1, 0xAA)
|
||||||
|
chip.cmd(0xC2, 0x65)
|
||||||
|
chip.cmd(0xC3, 0x74)
|
||||||
|
chip.cmd(0xC4, 0x47)
|
||||||
|
chip.cmd(0xC5, 0x56)
|
||||||
|
chip.cmd(0xC6, 0x00)
|
||||||
|
chip.cmd(0xC7, 0x88)
|
||||||
|
chip.cmd(0xC8, 0x99)
|
||||||
|
chip.cmd(0xC9, 0x33)
|
||||||
|
chip.cmd(0xD0, 0x21)
|
||||||
|
chip.cmd(0xD1, 0xAA)
|
||||||
|
chip.cmd(0xD2, 0x65)
|
||||||
|
chip.cmd(0xD3, 0x74)
|
||||||
|
chip.cmd(0xD4, 0x47)
|
||||||
|
chip.cmd(0xD5, 0x56)
|
||||||
|
chip.cmd(0xD6, 0x00)
|
||||||
|
chip.cmd(0xD7, 0x88)
|
||||||
|
chip.cmd(0xD8, 0x99)
|
||||||
|
chip.cmd(0xD9, 0x33)
|
||||||
|
chip.cmd(0xF3, 0x01)
|
||||||
|
chip.cmd(0xF0, 0x00)
|
||||||
|
chip.cmd(0xF0, 0x01)
|
||||||
|
chip.cmd(0xF1, 0x01)
|
||||||
|
chip.cmd(0xA0, 0x0B)
|
||||||
|
chip.cmd(0xA3, 0x2A)
|
||||||
|
chip.cmd(0xA5, 0xC3)
|
||||||
|
chip.cmd(PIXFMT, 0x55)
|
||||||
|
|
||||||
|
|
||||||
DriverChip("Custom")
|
DriverChip("Custom")
|
||||||
|
|
|
@ -33,19 +33,12 @@ void QspiDbi::update() {
|
||||||
this->do_update_();
|
this->do_update_();
|
||||||
if (this->buffer_ == nullptr || this->x_low_ > this->x_high_ || this->y_low_ > this->y_high_)
|
if (this->buffer_ == nullptr || this->x_low_ > this->x_high_ || this->y_low_ > this->y_high_)
|
||||||
return;
|
return;
|
||||||
// Start addresses and widths/heights must be divisible by 2 (CASET/RASET restriction in datasheet)
|
// Some chips require that the drawing window be aligned on certain boundaries
|
||||||
if (this->x_low_ % 2 == 1) {
|
auto dr = this->draw_rounding_;
|
||||||
this->x_low_--;
|
this->x_low_ = this->x_low_ / dr * dr;
|
||||||
}
|
this->y_low_ = this->y_low_ / dr * dr;
|
||||||
if (this->x_high_ % 2 == 0) {
|
this->x_high_ = (this->x_high_ + dr) / dr * dr - 1;
|
||||||
this->x_high_++;
|
this->y_high_ = (this->y_high_ + dr) / dr * dr - 1;
|
||||||
}
|
|
||||||
if (this->y_low_ % 2 == 1) {
|
|
||||||
this->y_low_--;
|
|
||||||
}
|
|
||||||
if (this->y_high_ % 2 == 0) {
|
|
||||||
this->y_high_++;
|
|
||||||
}
|
|
||||||
if (this->draw_from_origin_) {
|
if (this->draw_from_origin_) {
|
||||||
this->x_low_ = 0;
|
this->x_low_ = 0;
|
||||||
this->y_low_ = 0;
|
this->y_low_ = 0;
|
||||||
|
@ -175,10 +168,9 @@ void QspiDbi::write_to_display_(int x_start, int y_start, int w, int h, const ui
|
||||||
this->write_cmd_addr_data(8, 0x32, 24, 0x2C00, ptr, w * h * 2, 4);
|
this->write_cmd_addr_data(8, 0x32, 24, 0x2C00, ptr, w * h * 2, 4);
|
||||||
} else {
|
} else {
|
||||||
auto stride = x_offset + w + x_pad;
|
auto stride = x_offset + w + x_pad;
|
||||||
uint16_t cmd = 0x2C00;
|
this->write_cmd_addr_data(8, 0x32, 24, 0x2C00, nullptr, 0, 4);
|
||||||
for (int y = 0; y != h; y++) {
|
for (int y = 0; y != h; y++) {
|
||||||
this->write_cmd_addr_data(8, 0x32, 24, cmd, ptr + ((y + y_offset) * stride + x_offset) * 2, w * 2, 4);
|
this->write_cmd_addr_data(0, 0, 0, 0, ptr + ((y + y_offset) * stride + x_offset) * 2, w * 2, 4);
|
||||||
cmd = 0x3C00;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->disable();
|
this->disable();
|
||||||
|
@ -220,6 +212,7 @@ void QspiDbi::dump_config() {
|
||||||
ESP_LOGCONFIG("", "Model: %s", this->model_);
|
ESP_LOGCONFIG("", "Model: %s", this->model_);
|
||||||
ESP_LOGCONFIG(TAG, " Height: %u", this->height_);
|
ESP_LOGCONFIG(TAG, " Height: %u", this->height_);
|
||||||
ESP_LOGCONFIG(TAG, " Width: %u", this->width_);
|
ESP_LOGCONFIG(TAG, " Width: %u", this->width_);
|
||||||
|
ESP_LOGCONFIG(TAG, " Draw rounding: %u", this->draw_rounding_);
|
||||||
LOG_PIN(" CS Pin: ", this->cs_);
|
LOG_PIN(" CS Pin: ", this->cs_);
|
||||||
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
LOG_PIN(" Reset Pin: ", this->reset_pin_);
|
||||||
ESP_LOGCONFIG(TAG, " SPI Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000));
|
ESP_LOGCONFIG(TAG, " SPI Data rate: %dMHz", (unsigned) (this->data_rate_ / 1000000));
|
||||||
|
|
|
@ -4,12 +4,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#ifdef USE_ESP_IDF
|
#ifdef USE_ESP_IDF
|
||||||
#include "esphome/core/component.h"
|
|
||||||
#include "esphome/components/spi/spi.h"
|
#include "esphome/components/spi/spi.h"
|
||||||
#include "esphome/components/display/display.h"
|
#include "esphome/components/display/display.h"
|
||||||
#include "esphome/components/display/display_buffer.h"
|
#include "esphome/components/display/display_buffer.h"
|
||||||
#include "esphome/components/display/display_color_utils.h"
|
#include "esphome/components/display/display_color_utils.h"
|
||||||
#include "esp_lcd_panel_ops.h"
|
|
||||||
|
|
||||||
#include "esp_lcd_panel_rgb.h"
|
#include "esp_lcd_panel_rgb.h"
|
||||||
|
|
||||||
|
@ -105,6 +103,7 @@ class QspiDbi : public display::DisplayBuffer,
|
||||||
int get_height_internal() override { return this->height_; }
|
int get_height_internal() override { return this->height_; }
|
||||||
bool can_proceed() override { return this->setup_complete_; }
|
bool can_proceed() override { return this->setup_complete_; }
|
||||||
void add_init_sequence(const std::vector<uint8_t> &sequence) { this->init_sequences_.push_back(sequence); }
|
void add_init_sequence(const std::vector<uint8_t> &sequence) { this->init_sequences_.push_back(sequence); }
|
||||||
|
void set_draw_rounding(unsigned rounding) { this->draw_rounding_ = rounding; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void check_buffer_() {
|
void check_buffer_() {
|
||||||
|
@ -161,6 +160,7 @@ class QspiDbi : public display::DisplayBuffer,
|
||||||
bool mirror_x_{};
|
bool mirror_x_{};
|
||||||
bool mirror_y_{};
|
bool mirror_y_{};
|
||||||
bool draw_from_origin_{false};
|
bool draw_from_origin_{false};
|
||||||
|
unsigned draw_rounding_{2};
|
||||||
uint8_t brightness_{0xD0};
|
uint8_t brightness_{0xD0};
|
||||||
const char *model_{"Unknown"};
|
const char *model_{"Unknown"};
|
||||||
std::vector<std::vector<uint8_t>> init_sequences_{};
|
std::vector<std::vector<uint8_t>> init_sequences_{};
|
||||||
|
|
Loading…
Reference in a new issue