mirror of
https://github.com/esphome/esphome.git
synced 2024-11-29 10:14:13 +01:00
ili9341: use larger SPI transfers (#1628)
The original version uses write_byte to tranfer every byte of the display buffer which is quite extensive as every byte needs to be waited for in the SPI driver. This patch prepares transfers in 64-byte chunks. The result is a visible faster redraw of the display. Co-authored-by: Otto winter <otto@otto-winter.com>
This commit is contained in:
parent
9fe7b08874
commit
8e36e1b92e
2 changed files with 49 additions and 10 deletions
|
@ -93,12 +93,14 @@ void ILI9341Display::display_() {
|
||||||
this->start_data_();
|
this->start_data_();
|
||||||
uint32_t start_pos = ((this->y_low_ * this->width_) + x_low_);
|
uint32_t start_pos = ((this->y_low_ * this->width_) + x_low_);
|
||||||
for (uint16_t row = 0; row < h; row++) {
|
for (uint16_t row = 0; row < h; row++) {
|
||||||
for (uint16_t col = 0; col < w; col++) {
|
uint32_t pos = start_pos + (row * width_);
|
||||||
uint32_t pos = start_pos + (row * width_) + col;
|
uint32_t rem = w;
|
||||||
|
|
||||||
uint16_t color = convert_to_16bit_color_(buffer_[pos]);
|
while (rem > 0) {
|
||||||
this->write_byte(color >> 8);
|
uint32_t sz = buffer_to_transfer_(pos, rem);
|
||||||
this->write_byte(color);
|
this->write_array(transfer_buffer_, 2 * sz);
|
||||||
|
pos += sz;
|
||||||
|
rem -= sz;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->end_data_();
|
this->end_data_();
|
||||||
|
@ -140,16 +142,32 @@ void ILI9341Display::fill(Color color) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ILI9341Display::fill_internal_(Color color) {
|
void ILI9341Display::fill_internal_(Color color) {
|
||||||
|
if (color.raw_32 == COLOR_BLACK.raw_32) {
|
||||||
|
memset(transfer_buffer_, 0, sizeof(transfer_buffer_));
|
||||||
|
} else {
|
||||||
|
uint8_t *dst = transfer_buffer_;
|
||||||
|
auto color565 = display::ColorUtil::color_to_565(color);
|
||||||
|
|
||||||
|
while (dst < transfer_buffer_ + sizeof(transfer_buffer_)) {
|
||||||
|
*dst++ = (uint8_t)(color565 >> 8);
|
||||||
|
*dst++ = (uint8_t) color565;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t rem = this->get_width_internal() * this->get_height_internal();
|
||||||
|
|
||||||
this->set_addr_window_(0, 0, this->get_width_internal(), this->get_height_internal());
|
this->set_addr_window_(0, 0, this->get_width_internal(), this->get_height_internal());
|
||||||
this->start_data_();
|
this->start_data_();
|
||||||
|
|
||||||
auto color565 = display::ColorUtil::color_to_565(color);
|
while (rem > 0) {
|
||||||
for (uint32_t i = 0; i < (this->get_width_internal()) * (this->get_height_internal()); i++) {
|
size_t sz = rem <= sizeof(transfer_buffer_) ? rem : sizeof(transfer_buffer_);
|
||||||
this->write_byte(color565 >> 8);
|
this->write_array(transfer_buffer_, sz);
|
||||||
this->write_byte(color565);
|
rem -= sz;
|
||||||
buffer_[i] = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->end_data_();
|
this->end_data_();
|
||||||
|
|
||||||
|
memset(buffer_, 0, (this->get_width_internal()) * (this->get_height_internal()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void HOT ILI9341Display::draw_absolute_pixel_internal(int x, int y, Color color) {
|
void HOT ILI9341Display::draw_absolute_pixel_internal(int x, int y, Color color) {
|
||||||
|
@ -220,6 +238,23 @@ void ILI9341Display::invert_display_(bool invert) { this->command(invert ? ILI93
|
||||||
int ILI9341Display::get_width_internal() { return this->width_; }
|
int ILI9341Display::get_width_internal() { return this->width_; }
|
||||||
int ILI9341Display::get_height_internal() { return this->height_; }
|
int ILI9341Display::get_height_internal() { return this->height_; }
|
||||||
|
|
||||||
|
uint32_t ILI9341Display::buffer_to_transfer_(uint32_t pos, uint32_t sz) {
|
||||||
|
uint8_t *src = buffer_ + pos;
|
||||||
|
uint8_t *dst = transfer_buffer_;
|
||||||
|
|
||||||
|
if (sz > sizeof(transfer_buffer_) / 2) {
|
||||||
|
sz = sizeof(transfer_buffer_) / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < sz; ++i) {
|
||||||
|
uint16_t color = convert_to_16bit_color_(*src++);
|
||||||
|
*dst++ = (uint8_t)(color >> 8);
|
||||||
|
*dst++ = (uint8_t) color;
|
||||||
|
}
|
||||||
|
|
||||||
|
return sz;
|
||||||
|
}
|
||||||
|
|
||||||
// M5Stack display
|
// M5Stack display
|
||||||
void ILI9341M5Stack::initialize() {
|
void ILI9341M5Stack::initialize() {
|
||||||
this->init_lcd_(INITCMD_M5STACK);
|
this->init_lcd_(INITCMD_M5STACK);
|
||||||
|
|
|
@ -71,6 +71,10 @@ class ILI9341Display : public PollingComponent,
|
||||||
void start_data_();
|
void start_data_();
|
||||||
void end_data_();
|
void end_data_();
|
||||||
|
|
||||||
|
uint8_t transfer_buffer_[64];
|
||||||
|
|
||||||
|
uint32_t buffer_to_transfer_(uint32_t pos, uint32_t sz);
|
||||||
|
|
||||||
GPIOPin *reset_pin_{nullptr};
|
GPIOPin *reset_pin_{nullptr};
|
||||||
GPIOPin *led_pin_{nullptr};
|
GPIOPin *led_pin_{nullptr};
|
||||||
GPIOPin *dc_pin_;
|
GPIOPin *dc_pin_;
|
||||||
|
|
Loading…
Reference in a new issue