mirror of
https://github.com/esphome/esphome.git
synced 2025-10-18 17:53:47 +01:00
[mipi_spi] Rotation fixes (#11226)
This commit is contained in:
@@ -775,7 +775,7 @@ void Display::test_card() {
|
|||||||
int shift_y = (h - image_h) / 2;
|
int shift_y = (h - image_h) / 2;
|
||||||
int line_w = (image_w - 6) / 6;
|
int line_w = (image_w - 6) / 6;
|
||||||
int image_c = image_w / 2;
|
int image_c = image_w / 2;
|
||||||
for (auto i = 0; i <= image_h; i++) {
|
for (auto i = 0; i != image_h; i++) {
|
||||||
int c = esp_scale(i, image_h);
|
int c = esp_scale(i, image_h);
|
||||||
this->horizontal_line(shift_x + 0, shift_y + i, line_w, r.fade_to_white(c));
|
this->horizontal_line(shift_x + 0, shift_y + i, line_w, r.fade_to_white(c));
|
||||||
this->horizontal_line(shift_x + line_w, shift_y + i, line_w, r.fade_to_black(c)); //
|
this->horizontal_line(shift_x + line_w, shift_y + i, line_w, r.fade_to_black(c)); //
|
||||||
@@ -809,8 +809,11 @@ void Display::test_card() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->rectangle(0, 0, w, h, Color(127, 0, 127));
|
|
||||||
this->filled_rectangle(0, 0, 10, 10, Color(255, 0, 255));
|
this->filled_rectangle(0, 0, 10, 10, Color(255, 0, 255));
|
||||||
|
this->filled_rectangle(w - 10, 0, 10, 10, Color(255, 0, 255));
|
||||||
|
this->filled_rectangle(0, h - 10, 10, 10, Color(255, 0, 255));
|
||||||
|
this->filled_rectangle(w - 10, h - 10, 10, 10, Color(255, 0, 255));
|
||||||
|
this->rectangle(0, 0, w, h, Color(255, 255, 255));
|
||||||
this->stop_poller();
|
this->stop_poller();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@ from esphome.const import (
|
|||||||
CONF_BRIGHTNESS,
|
CONF_BRIGHTNESS,
|
||||||
CONF_COLOR_ORDER,
|
CONF_COLOR_ORDER,
|
||||||
CONF_DIMENSIONS,
|
CONF_DIMENSIONS,
|
||||||
|
CONF_DISABLED,
|
||||||
CONF_HEIGHT,
|
CONF_HEIGHT,
|
||||||
CONF_INIT_SEQUENCE,
|
CONF_INIT_SEQUENCE,
|
||||||
CONF_INVERT_COLORS,
|
CONF_INVERT_COLORS,
|
||||||
@@ -301,6 +302,8 @@ class DriverChip:
|
|||||||
Check if a rotation can be implemented in hardware using the MADCTL register.
|
Check if a rotation can be implemented in hardware using the MADCTL register.
|
||||||
A rotation of 180 is always possible if x and y mirroring are supported, 90 and 270 are possible if the model supports swapping X and Y.
|
A rotation of 180 is always possible if x and y mirroring are supported, 90 and 270 are possible if the model supports swapping X and Y.
|
||||||
"""
|
"""
|
||||||
|
if config.get(CONF_TRANSFORM) == CONF_DISABLED:
|
||||||
|
return False
|
||||||
transforms = self.transforms
|
transforms = self.transforms
|
||||||
rotation = config.get(CONF_ROTATION, 0)
|
rotation = config.get(CONF_ROTATION, 0)
|
||||||
if rotation == 0 or not transforms:
|
if rotation == 0 or not transforms:
|
||||||
@@ -358,26 +361,26 @@ class DriverChip:
|
|||||||
CONF_SWAP_XY: self.get_default(CONF_SWAP_XY),
|
CONF_SWAP_XY: self.get_default(CONF_SWAP_XY),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
# fill in defaults if not provided
|
if not isinstance(transform, dict):
|
||||||
mirror_x = transform.get(CONF_MIRROR_X, self.get_default(CONF_MIRROR_X))
|
# Presumably disabled
|
||||||
mirror_y = transform.get(CONF_MIRROR_Y, self.get_default(CONF_MIRROR_Y))
|
return {
|
||||||
swap_xy = transform.get(CONF_SWAP_XY, self.get_default(CONF_SWAP_XY))
|
CONF_MIRROR_X: False,
|
||||||
transform[CONF_MIRROR_X] = mirror_x
|
CONF_MIRROR_Y: False,
|
||||||
transform[CONF_MIRROR_Y] = mirror_y
|
CONF_SWAP_XY: False,
|
||||||
transform[CONF_SWAP_XY] = swap_xy
|
CONF_TRANSFORM: False,
|
||||||
|
}
|
||||||
# Can we use the MADCTL register to set the rotation?
|
# Can we use the MADCTL register to set the rotation?
|
||||||
if can_transform and CONF_TRANSFORM not in config:
|
if can_transform and CONF_TRANSFORM not in config:
|
||||||
rotation = config[CONF_ROTATION]
|
rotation = config[CONF_ROTATION]
|
||||||
if rotation == 180:
|
if rotation == 180:
|
||||||
transform[CONF_MIRROR_X] = not mirror_x
|
transform[CONF_MIRROR_X] = not transform[CONF_MIRROR_X]
|
||||||
transform[CONF_MIRROR_Y] = not mirror_y
|
transform[CONF_MIRROR_Y] = not transform[CONF_MIRROR_Y]
|
||||||
elif rotation == 90:
|
elif rotation == 90:
|
||||||
transform[CONF_SWAP_XY] = not swap_xy
|
transform[CONF_SWAP_XY] = not transform[CONF_SWAP_XY]
|
||||||
transform[CONF_MIRROR_X] = not mirror_x
|
transform[CONF_MIRROR_X] = not transform[CONF_MIRROR_X]
|
||||||
else:
|
else:
|
||||||
transform[CONF_SWAP_XY] = not swap_xy
|
transform[CONF_SWAP_XY] = not transform[CONF_SWAP_XY]
|
||||||
transform[CONF_MIRROR_Y] = not mirror_y
|
transform[CONF_MIRROR_Y] = not transform[CONF_MIRROR_Y]
|
||||||
transform[CONF_TRANSFORM] = True
|
transform[CONF_TRANSFORM] = True
|
||||||
return transform
|
return transform
|
||||||
|
|
||||||
|
@@ -37,6 +37,7 @@ from esphome.const import (
|
|||||||
CONF_DATA_RATE,
|
CONF_DATA_RATE,
|
||||||
CONF_DC_PIN,
|
CONF_DC_PIN,
|
||||||
CONF_DIMENSIONS,
|
CONF_DIMENSIONS,
|
||||||
|
CONF_DISABLED,
|
||||||
CONF_ENABLE_PIN,
|
CONF_ENABLE_PIN,
|
||||||
CONF_ID,
|
CONF_ID,
|
||||||
CONF_INIT_SEQUENCE,
|
CONF_INIT_SEQUENCE,
|
||||||
@@ -146,12 +147,15 @@ def swap_xy_schema(model):
|
|||||||
def model_schema(config):
|
def model_schema(config):
|
||||||
model = MODELS[config[CONF_MODEL]]
|
model = MODELS[config[CONF_MODEL]]
|
||||||
bus_mode = config[CONF_BUS_MODE]
|
bus_mode = config[CONF_BUS_MODE]
|
||||||
transform = cv.Schema(
|
transform = cv.Any(
|
||||||
{
|
cv.Schema(
|
||||||
cv.Required(CONF_MIRROR_X): cv.boolean,
|
{
|
||||||
cv.Required(CONF_MIRROR_Y): cv.boolean,
|
cv.Required(CONF_MIRROR_X): cv.boolean,
|
||||||
**swap_xy_schema(model),
|
cv.Required(CONF_MIRROR_Y): cv.boolean,
|
||||||
}
|
**swap_xy_schema(model),
|
||||||
|
}
|
||||||
|
),
|
||||||
|
cv.one_of(CONF_DISABLED, lower=True),
|
||||||
)
|
)
|
||||||
# CUSTOM model will need to provide a custom init sequence
|
# CUSTOM model will need to provide a custom init sequence
|
||||||
iseqconf = (
|
iseqconf = (
|
||||||
@@ -160,7 +164,11 @@ def model_schema(config):
|
|||||||
else cv.Optional(CONF_INIT_SEQUENCE)
|
else cv.Optional(CONF_INIT_SEQUENCE)
|
||||||
)
|
)
|
||||||
# Dimensions are optional if the model has a default width and the x-y transform is not overridden
|
# Dimensions are optional if the model has a default width and the x-y transform is not overridden
|
||||||
is_swapped = config.get(CONF_TRANSFORM, {}).get(CONF_SWAP_XY) is True
|
transform_config = config.get(CONF_TRANSFORM, {})
|
||||||
|
is_swapped = (
|
||||||
|
isinstance(transform_config, dict)
|
||||||
|
and transform_config.get(CONF_SWAP_XY, False) is True
|
||||||
|
)
|
||||||
cv_dimensions = (
|
cv_dimensions = (
|
||||||
cv.Optional if model.get_default(CONF_WIDTH) and not is_swapped else cv.Required
|
cv.Optional if model.get_default(CONF_WIDTH) and not is_swapped else cv.Required
|
||||||
)
|
)
|
||||||
@@ -192,9 +200,7 @@ def model_schema(config):
|
|||||||
.extend(
|
.extend(
|
||||||
{
|
{
|
||||||
cv.GenerateID(): cv.declare_id(MipiSpi),
|
cv.GenerateID(): cv.declare_id(MipiSpi),
|
||||||
cv_dimensions(CONF_DIMENSIONS): dimension_schema(
|
cv_dimensions(CONF_DIMENSIONS): dimension_schema(1),
|
||||||
model.get_default(CONF_DRAW_ROUNDING, 1)
|
|
||||||
),
|
|
||||||
model.option(CONF_ENABLE_PIN, cv.UNDEFINED): cv.ensure_list(
|
model.option(CONF_ENABLE_PIN, cv.UNDEFINED): cv.ensure_list(
|
||||||
pins.gpio_output_pin_schema
|
pins.gpio_output_pin_schema
|
||||||
),
|
),
|
||||||
@@ -400,6 +406,7 @@ def get_instance(config):
|
|||||||
offset_height,
|
offset_height,
|
||||||
DISPLAY_ROTATIONS[rotation],
|
DISPLAY_ROTATIONS[rotation],
|
||||||
frac,
|
frac,
|
||||||
|
config[CONF_DRAW_ROUNDING],
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
return MipiSpiBuffer, templateargs
|
return MipiSpiBuffer, templateargs
|
||||||
@@ -431,7 +438,6 @@ async def to_code(config):
|
|||||||
else:
|
else:
|
||||||
config[CONF_ROTATION] = 0
|
config[CONF_ROTATION] = 0
|
||||||
cg.add(var.set_model(config[CONF_MODEL]))
|
cg.add(var.set_model(config[CONF_MODEL]))
|
||||||
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(pin) for pin in enable_pin]
|
enable = [await cg.gpio_pin_expression(pin) for pin in enable_pin]
|
||||||
cg.add(var.set_enable_pins(enable))
|
cg.add(var.set_enable_pins(enable))
|
||||||
|
@@ -38,7 +38,7 @@ static constexpr uint8_t MADCTL_BGR = 0x08; // Bit 3 Blue-Green-Red pixel ord
|
|||||||
static constexpr uint8_t MADCTL_XFLIP = 0x02; // Mirror the display horizontally
|
static constexpr uint8_t MADCTL_XFLIP = 0x02; // Mirror the display horizontally
|
||||||
static constexpr uint8_t MADCTL_YFLIP = 0x01; // Mirror the display vertically
|
static constexpr uint8_t MADCTL_YFLIP = 0x01; // Mirror the display vertically
|
||||||
|
|
||||||
static const uint8_t DELAY_FLAG = 0xFF;
|
static constexpr uint8_t DELAY_FLAG = 0xFF;
|
||||||
// store a 16 bit value in a buffer, big endian.
|
// store a 16 bit value in a buffer, big endian.
|
||||||
static inline void put16_be(uint8_t *buf, uint16_t value) {
|
static inline void put16_be(uint8_t *buf, uint16_t value) {
|
||||||
buf[0] = value >> 8;
|
buf[0] = value >> 8;
|
||||||
@@ -79,7 +79,7 @@ class MipiSpi : public display::Display,
|
|||||||
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
|
public spi::SPIDevice<spi::BIT_ORDER_MSB_FIRST, spi::CLOCK_POLARITY_LOW, spi::CLOCK_PHASE_LEADING,
|
||||||
spi::DATA_RATE_1MHZ> {
|
spi::DATA_RATE_1MHZ> {
|
||||||
public:
|
public:
|
||||||
MipiSpi() {}
|
MipiSpi() = default;
|
||||||
void update() override { this->stop_poller(); }
|
void update() override { this->stop_poller(); }
|
||||||
void draw_pixel_at(int x, int y, Color color) override {}
|
void draw_pixel_at(int x, int y, Color color) override {}
|
||||||
void set_model(const char *model) { this->model_ = model; }
|
void set_model(const char *model) { this->model_ = model; }
|
||||||
@@ -99,7 +99,6 @@ class MipiSpi : public display::Display,
|
|||||||
int get_width_internal() override { return WIDTH; }
|
int get_width_internal() override { return WIDTH; }
|
||||||
int get_height_internal() override { return HEIGHT; }
|
int get_height_internal() override { return HEIGHT; }
|
||||||
void set_init_sequence(const std::vector<uint8_t> &sequence) { this->init_sequence_ = sequence; }
|
void set_init_sequence(const std::vector<uint8_t> &sequence) { this->init_sequence_ = sequence; }
|
||||||
void set_draw_rounding(unsigned rounding) { this->draw_rounding_ = rounding; }
|
|
||||||
|
|
||||||
// reset the display, and write the init sequence
|
// reset the display, and write the init sequence
|
||||||
void setup() override {
|
void setup() override {
|
||||||
@@ -326,6 +325,7 @@ class MipiSpi : public display::Display,
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes a buffer to the display.
|
* Writes a buffer to the display.
|
||||||
|
* @param ptr The pointer to the pixel data
|
||||||
* @param w Width of each line in bytes
|
* @param w Width of each line in bytes
|
||||||
* @param h Height of the buffer in rows
|
* @param h Height of the buffer in rows
|
||||||
* @param pad Padding in bytes after each line
|
* @param pad Padding in bytes after each line
|
||||||
@@ -424,7 +424,6 @@ class MipiSpi : public display::Display,
|
|||||||
|
|
||||||
// other properties set by configuration
|
// other properties set by configuration
|
||||||
bool invert_colors_{};
|
bool invert_colors_{};
|
||||||
unsigned draw_rounding_{2};
|
|
||||||
optional<uint8_t> brightness_{};
|
optional<uint8_t> brightness_{};
|
||||||
const char *model_{"Unknown"};
|
const char *model_{"Unknown"};
|
||||||
std::vector<uint8_t> init_sequence_{};
|
std::vector<uint8_t> init_sequence_{};
|
||||||
@@ -444,12 +443,20 @@ class MipiSpi : public display::Display,
|
|||||||
* @tparam OFFSET_WIDTH The x-offset of the display in pixels
|
* @tparam OFFSET_WIDTH The x-offset of the display in pixels
|
||||||
* @tparam OFFSET_HEIGHT The y-offset of the display in pixels
|
* @tparam OFFSET_HEIGHT The y-offset of the display in pixels
|
||||||
* @tparam FRACTION The fraction of the display size to use for the buffer (e.g. 4 means a 1/4 buffer).
|
* @tparam FRACTION The fraction of the display size to use for the buffer (e.g. 4 means a 1/4 buffer).
|
||||||
|
* @tparam ROUNDING The alignment requirement for drawing operations (e.g. 2 means that x coordinates must be even)
|
||||||
*/
|
*/
|
||||||
template<typename BUFFERTYPE, PixelMode BUFFERPIXEL, bool IS_BIG_ENDIAN, PixelMode DISPLAYPIXEL, BusType BUS_TYPE,
|
template<typename BUFFERTYPE, PixelMode BUFFERPIXEL, bool IS_BIG_ENDIAN, PixelMode DISPLAYPIXEL, BusType BUS_TYPE,
|
||||||
int WIDTH, int HEIGHT, int OFFSET_WIDTH, int OFFSET_HEIGHT, display::DisplayRotation ROTATION, int FRACTION>
|
uint16_t WIDTH, uint16_t HEIGHT, int OFFSET_WIDTH, int OFFSET_HEIGHT, display::DisplayRotation ROTATION,
|
||||||
|
int FRACTION, unsigned ROUNDING>
|
||||||
class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DISPLAYPIXEL, BUS_TYPE, WIDTH, HEIGHT,
|
class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DISPLAYPIXEL, BUS_TYPE, WIDTH, HEIGHT,
|
||||||
OFFSET_WIDTH, OFFSET_HEIGHT> {
|
OFFSET_WIDTH, OFFSET_HEIGHT> {
|
||||||
public:
|
public:
|
||||||
|
// these values define the buffer size needed to write in accordance with the chip pixel alignment
|
||||||
|
// requirements. If the required rounding does not divide the width and height, we round up to the next multiple and
|
||||||
|
// ignore the extra columns and rows when drawing, but use them to write to the display.
|
||||||
|
static constexpr unsigned BUFFER_WIDTH = (WIDTH + ROUNDING - 1) / ROUNDING * ROUNDING;
|
||||||
|
static constexpr unsigned BUFFER_HEIGHT = (HEIGHT + ROUNDING - 1) / ROUNDING * ROUNDING;
|
||||||
|
|
||||||
MipiSpiBuffer() { this->rotation_ = ROTATION; }
|
MipiSpiBuffer() { this->rotation_ = ROTATION; }
|
||||||
|
|
||||||
void dump_config() override {
|
void dump_config() override {
|
||||||
@@ -461,15 +468,15 @@ class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DIS
|
|||||||
" Buffer fraction: 1/%d\n"
|
" Buffer fraction: 1/%d\n"
|
||||||
" Buffer bytes: %zu\n"
|
" Buffer bytes: %zu\n"
|
||||||
" Draw rounding: %u",
|
" Draw rounding: %u",
|
||||||
this->rotation_, BUFFERPIXEL * 8, FRACTION, sizeof(BUFFERTYPE) * WIDTH * HEIGHT / FRACTION,
|
this->rotation_, BUFFERPIXEL * 8, FRACTION,
|
||||||
this->draw_rounding_);
|
sizeof(BUFFERTYPE) * BUFFER_WIDTH * BUFFER_HEIGHT / FRACTION, ROUNDING);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup() override {
|
void setup() override {
|
||||||
MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DISPLAYPIXEL, BUS_TYPE, WIDTH, HEIGHT, OFFSET_WIDTH,
|
MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DISPLAYPIXEL, BUS_TYPE, WIDTH, HEIGHT, OFFSET_WIDTH,
|
||||||
OFFSET_HEIGHT>::setup();
|
OFFSET_HEIGHT>::setup();
|
||||||
RAMAllocator<BUFFERTYPE> allocator{};
|
RAMAllocator<BUFFERTYPE> allocator{};
|
||||||
this->buffer_ = allocator.allocate(WIDTH * HEIGHT / FRACTION);
|
this->buffer_ = allocator.allocate(BUFFER_WIDTH * BUFFER_HEIGHT / FRACTION);
|
||||||
if (this->buffer_ == nullptr) {
|
if (this->buffer_ == nullptr) {
|
||||||
this->mark_failed("Buffer allocation failed");
|
this->mark_failed("Buffer allocation failed");
|
||||||
}
|
}
|
||||||
@@ -508,15 +515,14 @@ class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DIS
|
|||||||
esph_log_v(TAG, "x_low %d, y_low %d, x_high %d, y_high %d", this->x_low_, this->y_low_, this->x_high_,
|
esph_log_v(TAG, "x_low %d, y_low %d, x_high %d, y_high %d", this->x_low_, this->y_low_, this->x_high_,
|
||||||
this->y_high_);
|
this->y_high_);
|
||||||
// Some chips require that the drawing window be aligned on certain boundaries
|
// Some chips require that the drawing window be aligned on certain boundaries
|
||||||
auto dr = this->draw_rounding_;
|
this->x_low_ = this->x_low_ / ROUNDING * ROUNDING;
|
||||||
this->x_low_ = this->x_low_ / dr * dr;
|
this->y_low_ = this->y_low_ / ROUNDING * ROUNDING;
|
||||||
this->y_low_ = this->y_low_ / dr * dr;
|
this->x_high_ = (this->x_high_ + ROUNDING) / ROUNDING * ROUNDING - 1;
|
||||||
this->x_high_ = (this->x_high_ + dr) / dr * dr - 1;
|
this->y_high_ = (this->y_high_ + ROUNDING) / ROUNDING * ROUNDING - 1;
|
||||||
this->y_high_ = (this->y_high_ + dr) / dr * dr - 1;
|
|
||||||
int w = this->x_high_ - this->x_low_ + 1;
|
int w = this->x_high_ - this->x_low_ + 1;
|
||||||
int h = this->y_high_ - this->y_low_ + 1;
|
int h = this->y_high_ - this->y_low_ + 1;
|
||||||
this->write_to_display_(this->x_low_, this->y_low_, w, h, this->buffer_, this->x_low_,
|
this->write_to_display_(this->x_low_, this->y_low_, w, h, this->buffer_, this->x_low_,
|
||||||
this->y_low_ - this->start_line_, WIDTH - w);
|
this->y_low_ - this->start_line_, BUFFER_WIDTH - w);
|
||||||
// invalidate watermarks
|
// invalidate watermarks
|
||||||
this->x_low_ = WIDTH;
|
this->x_low_ = WIDTH;
|
||||||
this->y_low_ = HEIGHT;
|
this->y_low_ = HEIGHT;
|
||||||
@@ -536,10 +542,10 @@ class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DIS
|
|||||||
void draw_pixel_at(int x, int y, Color color) override {
|
void draw_pixel_at(int x, int y, Color color) override {
|
||||||
if (!this->get_clipping().inside(x, y))
|
if (!this->get_clipping().inside(x, y))
|
||||||
return;
|
return;
|
||||||
rotate_coordinates_(x, y);
|
rotate_coordinates(x, y);
|
||||||
if (x < 0 || x >= WIDTH || y < this->start_line_ || y >= this->end_line_)
|
if (x < 0 || x >= WIDTH || y < this->start_line_ || y >= this->end_line_)
|
||||||
return;
|
return;
|
||||||
this->buffer_[(y - this->start_line_) * WIDTH + x] = convert_color_(color);
|
this->buffer_[(y - this->start_line_) * BUFFER_WIDTH + x] = convert_color(color);
|
||||||
if (x < this->x_low_) {
|
if (x < this->x_low_) {
|
||||||
this->x_low_ = x;
|
this->x_low_ = x;
|
||||||
}
|
}
|
||||||
@@ -560,7 +566,7 @@ class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DIS
|
|||||||
this->y_low_ = this->start_line_;
|
this->y_low_ = this->start_line_;
|
||||||
this->x_high_ = WIDTH - 1;
|
this->x_high_ = WIDTH - 1;
|
||||||
this->y_high_ = this->end_line_ - 1;
|
this->y_high_ = this->end_line_ - 1;
|
||||||
std::fill_n(this->buffer_, HEIGHT * WIDTH / FRACTION, convert_color_(color));
|
std::fill_n(this->buffer_, HEIGHT * BUFFER_WIDTH / FRACTION, convert_color(color));
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_width() override {
|
int get_width() override {
|
||||||
@@ -577,7 +583,7 @@ class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DIS
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
// Rotate the coordinates to match the display orientation.
|
// Rotate the coordinates to match the display orientation.
|
||||||
void rotate_coordinates_(int &x, int &y) const {
|
static void rotate_coordinates(int &x, int &y) {
|
||||||
if constexpr (ROTATION == display::DISPLAY_ROTATION_180_DEGREES) {
|
if constexpr (ROTATION == display::DISPLAY_ROTATION_180_DEGREES) {
|
||||||
x = WIDTH - x - 1;
|
x = WIDTH - x - 1;
|
||||||
y = HEIGHT - y - 1;
|
y = HEIGHT - y - 1;
|
||||||
@@ -593,7 +599,7 @@ class MipiSpiBuffer : public MipiSpi<BUFFERTYPE, BUFFERPIXEL, IS_BIG_ENDIAN, DIS
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Convert a color to the buffer pixel format.
|
// Convert a color to the buffer pixel format.
|
||||||
BUFFERTYPE convert_color_(Color &color) const {
|
static BUFFERTYPE convert_color(const Color &color) {
|
||||||
if constexpr (BUFFERPIXEL == PIXEL_MODE_8) {
|
if constexpr (BUFFERPIXEL == PIXEL_MODE_8) {
|
||||||
return (color.red & 0xE0) | (color.g & 0xE0) >> 3 | color.b >> 6;
|
return (color.red & 0xE0) | (color.g & 0xE0) >> 3 | color.b >> 6;
|
||||||
} else if constexpr (BUFFERPIXEL == PIXEL_MODE_16) {
|
} else if constexpr (BUFFERPIXEL == PIXEL_MODE_16) {
|
||||||
|
@@ -3,6 +3,7 @@ import esphome.config_validation as cv
|
|||||||
|
|
||||||
from .amoled import CO5300
|
from .amoled import CO5300
|
||||||
from .ili import ILI9488_A
|
from .ili import ILI9488_A
|
||||||
|
from .jc import AXS15231
|
||||||
|
|
||||||
DriverChip(
|
DriverChip(
|
||||||
"WAVESHARE-4-TFT",
|
"WAVESHARE-4-TFT",
|
||||||
@@ -152,3 +153,12 @@ CO5300.extend(
|
|||||||
cs_pin=12,
|
cs_pin=12,
|
||||||
reset_pin=39,
|
reset_pin=39,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
AXS15231.extend(
|
||||||
|
"WAVESHARE-ESP32-S3-TOUCH-LCD-3.49",
|
||||||
|
width=172,
|
||||||
|
height=640,
|
||||||
|
data_rate="80MHz",
|
||||||
|
cs_pin=9,
|
||||||
|
reset_pin=21,
|
||||||
|
)
|
||||||
|
@@ -69,7 +69,7 @@ def run_schema_validation(config: ConfigType) -> None:
|
|||||||
{
|
{
|
||||||
"id": "display_id",
|
"id": "display_id",
|
||||||
"model": "custom",
|
"model": "custom",
|
||||||
"dimensions": {"width": 320, "height": 240},
|
"dimensions": {"width": 260, "height": 260},
|
||||||
"draw_rounding": 13,
|
"draw_rounding": 13,
|
||||||
"init_sequence": [[0xA0, 0x01]],
|
"init_sequence": [[0xA0, 0x01]],
|
||||||
},
|
},
|
||||||
@@ -336,7 +336,7 @@ def test_native_generation(
|
|||||||
|
|
||||||
main_cpp = generate_main(component_fixture_path("native.yaml"))
|
main_cpp = generate_main(component_fixture_path("native.yaml"))
|
||||||
assert (
|
assert (
|
||||||
"mipi_spi::MipiSpiBuffer<uint16_t, mipi_spi::PIXEL_MODE_16, true, mipi_spi::PIXEL_MODE_16, mipi_spi::BUS_TYPE_QUAD, 360, 360, 0, 1, display::DISPLAY_ROTATION_0_DEGREES, 1>()"
|
"mipi_spi::MipiSpiBuffer<uint16_t, mipi_spi::PIXEL_MODE_16, true, mipi_spi::PIXEL_MODE_16, mipi_spi::BUS_TYPE_QUAD, 360, 360, 0, 1, display::DISPLAY_ROTATION_0_DEGREES, 1, 1>()"
|
||||||
in main_cpp
|
in main_cpp
|
||||||
)
|
)
|
||||||
assert "set_init_sequence({240, 1, 8, 242" in main_cpp
|
assert "set_init_sequence({240, 1, 8, 242" in main_cpp
|
||||||
|
@@ -7,8 +7,8 @@ display:
|
|||||||
id: ili9xxx_display
|
id: ili9xxx_display
|
||||||
model: GC9A01A
|
model: GC9A01A
|
||||||
invert_colors: True
|
invert_colors: True
|
||||||
cs_pin: 10
|
cs_pin: 11
|
||||||
dc_pin: 6
|
dc_pin: 7
|
||||||
pages:
|
pages:
|
||||||
- id: page1
|
- id: page1
|
||||||
lambda: |-
|
lambda: |-
|
||||||
|
@@ -10,7 +10,7 @@ display:
|
|||||||
invert_colors: true
|
invert_colors: true
|
||||||
show_test_card: true
|
show_test_card: true
|
||||||
spi_mode: mode0
|
spi_mode: mode0
|
||||||
draw_rounding: 8
|
draw_rounding: 4
|
||||||
use_axis_flips: true
|
use_axis_flips: true
|
||||||
init_sequence:
|
init_sequence:
|
||||||
- [0xd0, 1, 2, 3]
|
- [0xd0, 1, 2, 3]
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
substitutions:
|
substitutions:
|
||||||
dc_pin: GPIO14
|
dc_pin: GPIO14
|
||||||
cs_pin: GPIO13
|
cs_pin: GPIO13
|
||||||
enable_pin: GPIO16
|
enable_pin: GPIO17
|
||||||
reset_pin: GPIO20
|
reset_pin: GPIO20
|
||||||
|
|
||||||
packages:
|
packages:
|
||||||
|
Reference in New Issue
Block a user