3#if defined(ESP_PLATFORM) && CONFIG_IDF_TARGET_ESP32S3
6#include "esp_heap_caps.h"
7#include "esp_idf_version.h"
8#include "esp_lcd_panel_ops.h"
9#include "roo_backport.h"
10#include "roo_backport/byte.h"
14#if ESP_IDF_VERSION < ESP_IDF_VERSION_VAL(5, 1, 0)
15#define LEGACY_RGBPANEL
21#include "esp_lcd_panel_rgb.h"
26namespace esp32s3_dma {
28roo::byte *AllocateBuffer(
const Config &config) {
29 esp_lcd_rgb_panel_config_t *cfg = (esp_lcd_rgb_panel_config_t *)calloc(
30 1,
sizeof(esp_lcd_rgb_panel_config_t));
32 cfg->clk_src = LCD_CLK_SRC_PLL160M;
35#ifdef CONFIG_SPIRAM_MODE_QUAD
36 int32_t default_speed = 6500000L;
38 int32_t default_speed = 13000000L;
44 int32_t default_speed = 18000000L;
48 cfg->timings.pclk_hz =
49 (config.prefer_speed == -1) ? default_speed : config.prefer_speed;
50 cfg->timings.h_res = config.width;
51 cfg->timings.v_res = config.height;
53 cfg->timings.hsync_pulse_width = config.hsync_pulse_width;
54 cfg->timings.hsync_back_porch = config.hsync_back_porch;
55 cfg->timings.hsync_front_porch = config.hsync_front_porch;
56 cfg->timings.vsync_pulse_width = config.vsync_pulse_width;
57 cfg->timings.vsync_back_porch = config.vsync_back_porch;
58 cfg->timings.vsync_front_porch = config.vsync_front_porch;
59 cfg->timings.flags.hsync_idle_low = (config.hsync_polarity == 0) ? 1 : 0;
60 cfg->timings.flags.vsync_idle_low = (config.vsync_polarity == 0) ? 1 : 0;
61 cfg->timings.flags.de_idle_high = 0;
62 cfg->timings.flags.pclk_active_neg = config.pclk_active_neg;
63 cfg->timings.flags.pclk_idle_high = 0;
68 cfg->sram_trans_align = 8;
69 cfg->psram_trans_align = 64;
71 cfg->hsync_gpio_num = config.hsync;
72 cfg->vsync_gpio_num = config.vsync;
73 cfg->de_gpio_num = config.de;
74 cfg->pclk_gpio_num = config.pclk;
76#ifndef LEGACY_RGBPANEL
77 cfg->bounce_buffer_size_px = 10 * config.width;
78 cfg->dma_burst_size = 32;
82 cfg->data_gpio_nums[0] = config.g3;
83 cfg->data_gpio_nums[1] = config.g4;
84 cfg->data_gpio_nums[2] = config.g5;
85 cfg->data_gpio_nums[3] = config.r0;
86 cfg->data_gpio_nums[4] = config.r1;
87 cfg->data_gpio_nums[5] = config.r2;
88 cfg->data_gpio_nums[6] = config.r3;
89 cfg->data_gpio_nums[7] = config.r4;
90 cfg->data_gpio_nums[8] = config.b0;
91 cfg->data_gpio_nums[9] = config.b1;
92 cfg->data_gpio_nums[10] = config.b2;
93 cfg->data_gpio_nums[11] = config.b3;
94 cfg->data_gpio_nums[12] = config.b4;
95 cfg->data_gpio_nums[13] = config.g0;
96 cfg->data_gpio_nums[14] = config.g1;
97 cfg->data_gpio_nums[15] = config.g2;
99 cfg->data_gpio_nums[0] = config.b0;
100 cfg->data_gpio_nums[1] = config.b1;
101 cfg->data_gpio_nums[2] = config.b2;
102 cfg->data_gpio_nums[3] = config.b3;
103 cfg->data_gpio_nums[4] = config.b4;
104 cfg->data_gpio_nums[5] = config.g0;
105 cfg->data_gpio_nums[6] = config.g1;
106 cfg->data_gpio_nums[7] = config.g2;
107 cfg->data_gpio_nums[8] = config.g3;
108 cfg->data_gpio_nums[9] = config.g4;
109 cfg->data_gpio_nums[10] = config.g5;
110 cfg->data_gpio_nums[11] = config.r0;
111 cfg->data_gpio_nums[12] = config.r1;
112 cfg->data_gpio_nums[13] = config.r2;
113 cfg->data_gpio_nums[14] = config.r3;
114 cfg->data_gpio_nums[15] = config.r4;
117 cfg->disp_gpio_num = -1;
119 cfg->flags.disp_active_low = 0;
121#if defined(LEGACY_RGBPANEL)
122 cfg->flags.relax_on_idle = 0;
127 cfg->flags.fb_in_psram = 1;
129 esp_lcd_panel_handle_t handle;
130 ESP_ERROR_CHECK(esp_lcd_new_rgb_panel(cfg, &handle));
131 ESP_ERROR_CHECK(esp_lcd_panel_reset(handle));
132 ESP_ERROR_CHECK(esp_lcd_panel_init(handle));
135 esp_lcd_rgb_panel_get_frame_buffer(handle, 1, (
void **)&buf);
140void ParallelRgb565<FLUSH_MODE_AGGRESSIVE>::init() {
142 roo::byte *buffer = AllocateBuffer(cfg_);
143 buffer_.reset(
new Dev(cfg_.width, cfg_.height, buffer,
144 ::roo_display::internal::Rgb565Dma()));
145 buffer_->setOrientation(orientation());
149void ParallelRgb565<FLUSH_MODE_AGGRESSIVE>::end() {
150 if (buffer_ !=
nullptr) {
156void ParallelRgb565<FLUSH_MODE_AGGRESSIVE>::write(Color *color,
157 uint32_t pixel_count) {
158 buffer_->write(color, pixel_count);
162void ParallelRgb565<FLUSH_MODE_AGGRESSIVE>::writePixels(
BlendingMode mode,
164 int16_t *x, int16_t *y,
165 uint16_t pixel_count) {
166 buffer_->writePixels(mode, color, x, y, pixel_count);
170void ParallelRgb565<FLUSH_MODE_AGGRESSIVE>::fillPixels(
BlendingMode mode,
171 Color color, int16_t *x,
173 uint16_t pixel_count) {
174 buffer_->fillPixels(mode, color, x, y, pixel_count);
178void ParallelRgb565<FLUSH_MODE_AGGRESSIVE>::writeRects(
BlendingMode mode,
180 int16_t *x0, int16_t *y0,
181 int16_t *x1, int16_t *y1,
183 buffer_->writeRects(mode, color, x0, y0, x1, y1, count);
187void ParallelRgb565<FLUSH_MODE_AGGRESSIVE>::fillRects(
BlendingMode mode,
188 Color color, int16_t *x0,
189 int16_t *y0, int16_t *x1,
192 buffer_->fillRects(mode, color, x0, y0, x1, y1, count);
196void ParallelRgb565<FLUSH_MODE_AGGRESSIVE>::drawDirectRect(
197 const roo::byte *data,
size_t row_width_bytes, int16_t src_x0,
198 int16_t src_y0, int16_t src_x1, int16_t src_y1, int16_t dst_x0,
200 buffer_->drawDirectRect(data, row_width_bytes, src_x0, src_y0, src_x1, src_y1,
203 constexpr uint32_t kBytesPerPixel = 2;
204 int16_t height = src_y1 - src_y0 + 1;
206 static_cast<uint32_t
>(dst_y0) * cfg_.width * kBytesPerPixel;
208 static_cast<uint32_t
>(height) * cfg_.width * kBytesPerPixel;
209 Cache_WriteBack_Addr((uint32_t)buffer_->buffer() + offset, length);
211 Cache_WriteBack_Addr((uint32_t)buffer_->buffer(),
212 cfg_.width * cfg_.height * 2);
217void ParallelRgb565<FLUSH_MODE_AGGRESSIVE>::drawDirectRectAsync(
218 const roo::byte *data,
size_t row_width_bytes, int16_t src_x0,
219 int16_t src_y0, int16_t src_x1, int16_t src_y1, int16_t dst_x0,
221 if (buffer_ ==
nullptr || src_x1 < src_x0 || src_y1 < src_y0)
return;
222 buffer_->drawDirectRectAsync(data, row_width_bytes, src_x0, src_y0, src_x1,
223 src_y1, dst_x0, dst_y0);
233inline FlushRange ResolveFlushRangeForRects(
const Config &cfg,
234 Orientation orientation,
235 int16_t *x0, int16_t *y0,
236 int16_t *x1, int16_t *y1,
238 if (orientation.isXYswapped()) {
242 int16_t ymin = *y0++;
243 int16_t ymax = *y1++;
244 while (--count > 0) {
245 ymin = std::min(ymin, *y0++);
246 ymax = std::max(ymax, *y1++);
249 .offset = orientation.isTopToBottom()
250 ? (uint32_t)(ymin * cfg.width * 2)
251 : (uint32_t)((cfg.height - ymax - 1) * cfg.width * 2),
252 .length = (uint32_t)((ymax - ymin + 1) * cfg.width * 2),
259void ParallelRgb565<FLUSH_MODE_BUFFERED>::init() {
261 roo::byte *buffer = AllocateBuffer(cfg_);
262 buffer_.reset(
new Dev(cfg_.width, cfg_.height, buffer, Rgb565()));
263 buffer_->setOrientation(orientation());
267void ParallelRgb565<FLUSH_MODE_BUFFERED>::end() {
268 if (buffer_ !=
nullptr) {
274void ParallelRgb565<FLUSH_MODE_BUFFERED>::write(Color *color,
275 uint32_t pixel_count) {
278 buffer_->write(color, pixel_count);
297void ParallelRgb565<FLUSH_MODE_BUFFERED>::fill(Color color,
298 uint32_t pixel_count) {
299 buffer_->fill(color, pixel_count);
304void ParallelRgb565<FLUSH_MODE_BUFFERED>::writePixels(
BlendingMode mode,
305 Color *color, int16_t *x,
307 uint16_t pixel_count) {
311 buffer_->writePixels(mode, color, x, y, pixel_count);
320void ParallelRgb565<FLUSH_MODE_BUFFERED>::fillPixels(
BlendingMode mode,
321 Color color, int16_t *x,
323 uint16_t pixel_count) {
327 buffer_->fillPixels(mode, color, x, y, pixel_count);
336void ParallelRgb565<FLUSH_MODE_BUFFERED>::writeRects(
BlendingMode mode,
337 Color *color, int16_t *x0,
338 int16_t *y0, int16_t *x1,
344 buffer_->writeRects(mode, color, x0, y0, x1, y1, count);
353void ParallelRgb565<FLUSH_MODE_BUFFERED>::fillRects(
BlendingMode mode,
354 Color color, int16_t *x0,
355 int16_t *y0, int16_t *x1,
361 buffer_->fillRects(mode, color, x0, y0, x1, y1, count);
370void ParallelRgb565<FLUSH_MODE_BUFFERED>::drawDirectRect(
371 const roo::byte *data,
size_t row_width_bytes, int16_t src_x0,
372 int16_t src_y0, int16_t src_x1, int16_t src_y1, int16_t dst_x0,
374 if (buffer_ ==
nullptr || src_x1 < src_x0 || src_y1 < src_y0)
return;
375 buffer_->drawDirectRect(data, row_width_bytes, src_x0, src_y0, src_x1, src_y1,
378 constexpr uint32_t kBytesPerPixel = 2;
379 int16_t height = src_y1 - src_y0 + 1;
381 static_cast<uint32_t
>(dst_y0) * cfg_.width * kBytesPerPixel;
383 static_cast<uint32_t
>(height) * cfg_.width * kBytesPerPixel;
384 Cache_WriteBack_Addr((uint32_t)buffer_->buffer() + offset, length);
386 Cache_WriteBack_Addr((uint32_t)buffer_->buffer(),
387 cfg_.width * cfg_.height * 2);
392void ParallelRgb565<FLUSH_MODE_BUFFERED>::drawDirectRectAsync(
393 const roo::byte *data,
size_t row_width_bytes, int16_t src_x0,
394 int16_t src_y0, int16_t src_x1, int16_t src_y1, int16_t dst_x0,
396 if (buffer_ ==
nullptr || src_x1 < src_x0 || src_y1 < src_y0)
return;
397 buffer_->drawDirectRectAsync(data, row_width_bytes, src_x0, src_y0, src_x1,
398 src_y1, dst_x0, dst_y0);
402void ParallelRgb565<FLUSH_MODE_LAZY>::init() {
404 roo::byte *buffer = AllocateBuffer(cfg_);
405 buffer_.reset(
new Dev(cfg_.width, cfg_.height, buffer, Rgb565()));
406 buffer_->setOrientation(orientation());
410void ParallelRgb565<FLUSH_MODE_LAZY>::end() {
411 if (buffer_ !=
nullptr) {
418void ParallelRgb565<FLUSH_MODE_LAZY>::write(Color *color,
419 uint32_t pixel_count) {
420 buffer_->write(color, pixel_count);
424void ParallelRgb565<FLUSH_MODE_LAZY>::fill(Color color, uint32_t pixel_count) {
425 buffer_->fill(color, pixel_count);
429void ParallelRgb565<FLUSH_MODE_LAZY>::writePixels(
BlendingMode mode,
430 Color *color, int16_t *x,
432 uint16_t pixel_count) {
433 buffer_->writePixels(mode, color, x, y, pixel_count);
437void ParallelRgb565<FLUSH_MODE_LAZY>::fillPixels(
BlendingMode mode, Color color,
438 int16_t *x, int16_t *y,
439 uint16_t pixel_count) {
440 buffer_->fillPixels(mode, color, x, y, pixel_count);
444void ParallelRgb565<FLUSH_MODE_LAZY>::writeRects(
BlendingMode mode,
445 Color *color, int16_t *x0,
446 int16_t *y0, int16_t *x1,
447 int16_t *y1, uint16_t count) {
448 buffer_->writeRects(mode, color, x0, y0, x1, y1, count);
452void ParallelRgb565<FLUSH_MODE_LAZY>::fillRects(
BlendingMode mode, Color color,
453 int16_t *x0, int16_t *y0,
454 int16_t *x1, int16_t *y1,
456 buffer_->fillRects(mode, color, x0, y0, x1, y1, count);
460void ParallelRgb565<FLUSH_MODE_LAZY>::drawDirectRect(
461 const roo::byte *data,
size_t row_width_bytes, int16_t src_x0,
462 int16_t src_y0, int16_t src_x1, int16_t src_y1, int16_t dst_x0,
464 if (buffer_ ==
nullptr || src_x1 < src_x0 || src_y1 < src_y0)
return;
465 buffer_->drawDirectRect(data, row_width_bytes, src_x0, src_y0, src_x1, src_y1,
470void ParallelRgb565<FLUSH_MODE_LAZY>::drawDirectRectAsync(
471 const roo::byte *data,
size_t row_width_bytes, int16_t src_x0,
472 int16_t src_y0, int16_t src_x1, int16_t src_y1, int16_t dst_x0,
474 if (buffer_ ==
nullptr || src_x1 < src_x0 || src_y1 < src_y0)
return;
475 buffer_->drawDirectRectAsync(data, row_width_bytes, src_x0, src_y0, src_x1,
476 src_y1, dst_x0, dst_y0);
static constexpr Orientation Default()
Return the default orientation (RightDown).
Defines 140 opaque HTML named colors.
BlendingMode
Porter-Duff style blending modes.