Skip to content

Commit 15c8f92

Browse files
committed
Fixes RGB Driver
Fixes 90° Rotation Fixes jerking of the UI Fixes flickering when the UI is first rendered Moves DMA ISR's to core 0 Moves Bus init to core 0
1 parent b46f799 commit 15c8f92

File tree

4 files changed

+247
-98
lines changed

4 files changed

+247
-98
lines changed

builder/esp32.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -342,11 +342,15 @@ def common_args(extra_args):
342342
return extra_args
343343

344344

345+
optimum_fb_size = '0'
346+
347+
345348
def esp32_s3_args(extra_args):
346349
global oct_flash
347350
global usb_otg
348351
global usb_jtag
349352
global board_variant
353+
global optimum_fb_size
350354

351355
esp_argParser = ArgumentParser(prefix_chars='-B')
352356

@@ -377,12 +381,22 @@ def esp32_s3_args(extra_args):
377381
action='store_true'
378382
)
379383

384+
esp_argParser.add_argument(
385+
'--enable_fb_test',
386+
dest='optimum_fb_size',
387+
default=False,
388+
action='store_true'
389+
)
390+
380391
esp_args, extra_args = esp_argParser.parse_known_args(extra_args)
381392

382393
oct_flash = esp_args.oct_flash
383394
usb_otg = esp_args.usb_otg
384395
usb_jtag = esp_args.usb_jtag
385396
board_variant = esp_args.board_variant
397+
optimum_fb_size = str(int(esp_args.optimum_fb_size))
398+
399+
os.environ['EXTRA_CFLAGS'] = f'-DLCD_RGB_OPTIMUM_FB_SIZE={optimum_fb_size}'
386400

387401
return extra_args
388402

@@ -684,6 +698,8 @@ def environ_helper(idf_path):
684698

685699
spawn(env_cmds, out_to_screen=False)
686700

701+
env['EXTRA_CFLAGS'] = f'-DLCD_RGB_OPTIMUM_FB_SIZE={optimum_fb_size}'
702+
687703
return env
688704

689705

@@ -777,6 +793,7 @@ def setup_idf_environ():
777793
else:
778794
cmds = []
779795

796+
env['EXTRA_CFLAGS'] = f'-DLCD_RGB_OPTIMUM_FB_SIZE={optimum_fb_size}'
780797
return env, cmds
781798

782799

ext_mod/lcd_bus/esp32_include/rgb_bus.h

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,14 @@
88
#include "lcd_types.h"
99

1010
// esp-idf includes
11+
#include "hal/lcd_hal.h"
12+
#include "esp_pm.h"
13+
#include "esp_intr_alloc.h"
14+
#include "esp_heap_caps.h"
15+
1116
#include "esp_lcd_panel_io.h"
17+
#include "esp_lcd_panel_ops.h"
18+
#include "esp_lcd_panel_interface.h"
1219
#include "esp_lcd_panel_rgb.h"
1320

1421
#include "freertos/FreeRTOS.h"
@@ -22,6 +29,24 @@
2229
#include "py/obj.h"
2330
#include "py/objarray.h"
2431

32+
typedef struct {
33+
esp_lcd_panel_t base; // Base class of generic lcd panel
34+
int panel_id; // LCD panel ID
35+
lcd_hal_context_t hal; // Hal layer object
36+
size_t data_width; // Number of data lines
37+
size_t fb_bits_per_pixel; // Frame buffer color depth, in bpp
38+
size_t num_fbs; // Number of frame buffers
39+
size_t output_bits_per_pixel; // Color depth seen from the output data line. Default to fb_bits_per_pixel, but can be changed by YUV-RGB conversion
40+
size_t sram_trans_align; // Alignment for framebuffer that allocated in SRAM
41+
size_t psram_trans_align; // Alignment for framebuffer that allocated in PSRAM
42+
int disp_gpio_num; // Display control GPIO, which is used to perform action like "disp_off"
43+
intr_handle_t intr; // LCD peripheral interrupt handle
44+
esp_pm_lock_handle_t pm_lock; // Power management lock
45+
size_t num_dma_nodes; // Number of DMA descriptors that used to carry the frame buffer
46+
uint8_t *fbs[3]; // Frame buffers
47+
uint8_t cur_fb_index; // Current frame buffer index
48+
uint8_t bb_fb_index; // Current frame buffer index which used by bounce buffer
49+
} rgb_panel_t;
2550

2651
typedef struct _rgb_bus_lock_t {
2752
SemaphoreHandle_t handle;
@@ -33,6 +58,15 @@
3358
StaticEventGroup_t buffer;
3459
} rgb_bus_event_t;
3560

61+
#if LCD_RGB_OPTIMUM_FB_SIZE
62+
typedef struct _rgb_bus_optimum_fb_size_t {
63+
uint16_t flush_count;
64+
uint8_t sample_count;
65+
uint8_t curr_index;
66+
uint16_t *samples;
67+
rgb_bus_lock_t lock;
68+
} rgb_bus_optimum_fb_size_t;
69+
#endif
3670

3771
typedef struct _mp_lcd_rgb_bus_obj_t {
3872
mp_obj_base_t base;
@@ -73,10 +107,17 @@
73107
rgb_bus_event_t copy_task_exit;
74108
rgb_bus_lock_t tx_color_lock;
75109
rgb_bus_event_t swap_bufs;
76-
rgb_bus_lock_t swap_lock;
110+
rgb_bus_lock_t init_lock;
77111

78112
TaskHandle_t copy_task_handle;
79113

114+
mp_lcd_err_t init_err;
115+
mp_rom_error_text_t init_err_msg;
116+
117+
#if LCD_RGB_OPTIMUM_FB_SIZE
118+
rgb_bus_optimum_fb_size_t optimum_fb;
119+
#endif
120+
80121
} mp_lcd_rgb_bus_obj_t;
81122

82123
void rgb_bus_event_init(rgb_bus_event_t *event);
@@ -87,6 +128,7 @@
87128
void rgb_bus_event_clear_from_isr(rgb_bus_event_t *event);
88129
bool rgb_bus_event_isset_from_isr(rgb_bus_event_t *event);
89130
void rgb_bus_event_set_from_isr(rgb_bus_event_t *event);
131+
void rgb_bus_event_wait(rgb_bus_event_t *event);
90132

91133
int rgb_bus_lock_acquire(rgb_bus_lock_t *lock, int32_t wait_ms);
92134
void rgb_bus_lock_release(rgb_bus_lock_t *lock);

ext_mod/lcd_bus/esp32_src/rgb_bus.c

Lines changed: 91 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -25,53 +25,16 @@
2525
#include "py/runtime.h"
2626
#include "py/objarray.h"
2727
#include "py/binary.h"
28+
#include "py/objint.h"
29+
#include "py/objstr.h"
30+
#include "py/objtype.h"
31+
#include "py/objexcept.h"
2832

2933
// stdlib includes
3034
#include <string.h>
3135

3236
#define DEFAULT_STACK_SIZE (5 * 1024)
3337

34-
35-
typedef struct {
36-
esp_lcd_panel_t base; // Base class of generic lcd panel
37-
int panel_id; // LCD panel ID
38-
lcd_hal_context_t hal; // Hal layer object
39-
size_t data_width; // Number of data lines
40-
size_t fb_bits_per_pixel; // Frame buffer color depth, in bpp
41-
size_t num_fbs; // Number of frame buffers
42-
size_t output_bits_per_pixel; // Color depth seen from the output data line. Default to fb_bits_per_pixel, but can be changed by YUV-RGB conversion
43-
size_t sram_trans_align; // Alignment for framebuffer that allocated in SRAM
44-
size_t psram_trans_align; // Alignment for framebuffer that allocated in PSRAM
45-
int disp_gpio_num; // Display control GPIO, which is used to perform action like "disp_off"
46-
intr_handle_t intr; // LCD peripheral interrupt handle
47-
esp_pm_lock_handle_t pm_lock; // Power management lock
48-
size_t num_dma_nodes; // Number of DMA descriptors that used to carry the frame buffer
49-
uint8_t *fbs[3]; // Frame buffers
50-
uint8_t cur_fb_index; // Current frame buffer index
51-
uint8_t bb_fb_index; // Current frame buffer index which used by bounce buffer
52-
} rgb_panel_t;
53-
54-
55-
static bool rgb_bus_trans_done_cb(esp_lcd_panel_handle_t panel, const esp_lcd_rgb_panel_event_data_t *edata, void *user_ctx)
56-
{
57-
LCD_UNUSED(edata);
58-
LCD_UNUSED(panel);
59-
// rgb_panel_t *rgb_panel = __containerof(panel, rgb_panel_t, base);
60-
mp_lcd_rgb_bus_obj_t *self = (mp_lcd_rgb_bus_obj_t *)user_ctx;
61-
62-
if (rgb_bus_event_isset_from_isr(&self->swap_bufs)) {
63-
rgb_bus_event_clear_from_isr(&self->swap_bufs);
64-
uint8_t *idle_fb = self->idle_fb;
65-
self->idle_fb = self->active_fb;
66-
self->active_fb = idle_fb;
67-
rgb_bus_lock_release_from_isr(&self->swap_lock);
68-
}
69-
70-
return false;
71-
}
72-
73-
esp_lcd_rgb_panel_event_callbacks_t callbacks = { .on_vsync = rgb_bus_trans_done_cb };
74-
7538
mp_lcd_err_t rgb_del(mp_obj_t obj);
7639
mp_lcd_err_t rgb_init(mp_obj_t obj, uint16_t width, uint16_t height, uint8_t bpp, uint32_t buffer_size, bool rgb565_byte_swap, uint8_t cmd_bits, uint8_t param_bits);
7740
mp_lcd_err_t rgb_get_lane_count(mp_obj_t obj, uint8_t *lane_count);
@@ -292,8 +255,8 @@
292255

293256
rgb_bus_lock_delete(&self->copy_lock);
294257
rgb_bus_lock_delete(&self->tx_color_lock);
295-
rgb_bus_lock_delete(&self->swap_lock);
296258

259+
rgb_bus_event_clear(&self->swap_bufs);
297260
rgb_bus_event_delete(&self->swap_bufs);
298261
rgb_bus_event_delete(&self->copy_task_exit);
299262

@@ -440,54 +403,43 @@
440403
self->panel_io_config.flags.fb_in_psram = 1;
441404
self->panel_io_config.flags.double_fb = 1;
442405

406+
rgb_bus_lock_init(&self->copy_lock);
407+
rgb_bus_lock_init(&self->tx_color_lock);
408+
rgb_bus_event_init(&self->copy_task_exit);
409+
rgb_bus_event_init(&self->swap_bufs);
410+
rgb_bus_event_set(&self->swap_bufs);
411+
rgb_bus_lock_init(&self->init_lock);
412+
rgb_bus_lock_acquire(&self->init_lock, -1);
413+
414+
415+
#if LCD_RGB_OPTIMUM_FB_SIZE
416+
rgb_bus_lock_init(&self->optimum_fb.lock);
417+
rgb_bus_lock_acquire(&self->optimum_fb.lock, -1);
418+
self->optimum_fb.samples = (uint16_t *)malloc(sizeof(uint16_t) * 255);
419+
self->optimum_fb.curr_index = 254;
420+
#endif
421+
443422
#if CONFIG_LCD_ENABLE_DEBUG_LOG
444423
mp_printf(&mp_plat_print, "h_res=%lu\n", self->panel_io_config.timings.h_res);
445424
mp_printf(&mp_plat_print, "v_res=%lu\n", self->panel_io_config.timings.v_res);
446425
mp_printf(&mp_plat_print, "bits_per_pixel=%d\n", self->panel_io_config.bits_per_pixel);
447426
mp_printf(&mp_plat_print, "rgb565_byte_swap=%d\n", self->rgb565_byte_swap);
448427
#endif
449-
mp_lcd_err_t ret = esp_lcd_new_rgb_panel(&self->panel_io_config, &self->panel_handle);
450-
if (ret != 0) {
451-
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%d(esp_lcd_new_rgb_panel)"), ret);
452-
return ret;
453-
}
454-
455-
if (self->panel_io_config.flags.double_fb) {
456-
ret = esp_lcd_rgb_panel_register_event_callbacks(self->panel_handle, &callbacks, self);
457-
if (ret != 0) {
458-
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%d(esp_lcd_rgb_panel_register_event_callbacks)"), ret);
459-
return ret;
460-
}
461-
}
462-
463-
ret = esp_lcd_panel_reset(self->panel_handle);
464-
if (ret != 0) {
465-
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%d(esp_lcd_panel_reset)"), ret);
466-
return ret;
467-
}
468-
469-
ret = esp_lcd_panel_init(self->panel_handle);
470-
if (ret != 0) {
471-
mp_raise_msg_varg(&mp_type_ValueError, MP_ERROR_TEXT("%d(esp_lcd_panel_init)"), ret);
472-
return ret;
473-
}
474-
475-
rgb_panel_t *rgb_panel = __containerof((esp_lcd_panel_t *)self->panel_handle, rgb_panel_t, base);
476-
477-
self->active_fb = rgb_panel->fbs[1];
478-
self->idle_fb = rgb_panel->fbs[0];
479-
480-
rgb_bus_lock_init(&self->copy_lock);
481-
rgb_bus_lock_init(&self->tx_color_lock);
482-
rgb_bus_event_init(&self->copy_task_exit);
483-
rgb_bus_event_init(&self->swap_bufs);
484-
rgb_bus_lock_init(&self->swap_lock);
485428

486429
xTaskCreatePinnedToCore(
487430
rgb_bus_copy_task, "rgb_task", DEFAULT_STACK_SIZE / sizeof(StackType_t),
488431
self, ESP_TASK_PRIO_MAX - 1, &self->copy_task_handle, 0);
489432

490-
return LCD_OK;
433+
rgb_bus_lock_acquire(&self->init_lock, -1);
434+
rgb_bus_lock_release(&self->init_lock);
435+
rgb_bus_lock_delete(&self->init_lock);
436+
437+
if (self->init_err != LCD_OK) {
438+
mp_raise_msg_varg(&mp_type_ValueError, self->init_err_msg, self->init_err);
439+
return self->init_err;
440+
} else {
441+
return LCD_OK;
442+
}
491443
}
492444

493445

@@ -528,13 +480,73 @@
528480
return LCD_OK;
529481
}
530482

483+
#if LCD_RGB_OPTIMUM_FB_SIZE
484+
485+
static void rgb_bus_attr(mp_obj_t self_in, qstr attr, mp_obj_t *dest)
486+
{
487+
mp_lcd_rgb_bus_obj_t *self = MP_OBJ_TO_PTR(self_in);
488+
489+
if (attr == MP_QSTR_avg_flushes_per_update) {
490+
if (dest[0] == MP_OBJ_NULL) {
491+
uint32_t total = 0;
492+
493+
rgb_bus_lock_acquire(&self->optimum_fb.lock, -1);
494+
for (uint8_t i=0;i<self->optimum_fb.sample_count;i++) {
495+
total += (uint32_t)self->optimum_fb.samples[i];
496+
}
497+
498+
uint16_t avg = (uint16_t)(total / (uint32_t)self->optimum_fb.sample_count);
499+
500+
rgb_bus_lock_release(&self->optimum_fb.lock);
501+
502+
dest[0] = mp_obj_new_int_from_uint(avg);
503+
} else if (dest[1]) {
504+
uint16_t value = (uint16_t)mp_obj_get_int_truncated(dest[1]);
505+
506+
if (value == 0) {
507+
rgb_bus_lock_acquire(&self->optimum_fb.lock, -1);
508+
for (uint8_t i=0;i<self->optimum_fb.sample_count;i++) {
509+
self->optimum_fb.samples[i] = 0;
510+
}
511+
512+
self->optimum_fb.sample_count = 0;
513+
self->optimum_fb.curr_index = 254;
514+
rgb_bus_lock_release(&self->optimum_fb.lock);
515+
516+
dest[0] = MP_OBJ_NULL;
517+
}
518+
}
519+
} else if (dest[0] == MP_OBJ_NULL) {
520+
const mp_obj_type_t *type = mp_obj_get_type(self_in);
521+
while (MP_OBJ_TYPE_HAS_SLOT(type, locals_dict)) {
522+
// generic method lookup
523+
// this is a lookup in the object (ie not class or type)
524+
assert(MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->base.type == &mp_type_dict); // MicroPython restriction, for now
525+
mp_map_t *locals_map = &MP_OBJ_TYPE_GET_SLOT(type, locals_dict)->map;
526+
mp_map_elem_t *elem = mp_map_lookup(locals_map, MP_OBJ_NEW_QSTR(attr), MP_MAP_LOOKUP);
527+
if (elem != NULL) {
528+
mp_convert_member_lookup(self_in, type, elem->value, dest);
529+
break;
530+
}
531+
if (MP_OBJ_TYPE_GET_SLOT_OR_NULL(type, parent) == NULL) break;
532+
// search parents
533+
type = MP_OBJ_TYPE_GET_SLOT(type, parent);
534+
}
535+
}
536+
}
537+
#endif
538+
531539
MP_DEFINE_CONST_OBJ_TYPE(
532540
mp_lcd_rgb_bus_type,
533541
MP_QSTR_RGBBus,
534542
MP_TYPE_FLAG_NONE,
535543
make_new, mp_lcd_rgb_bus_make_new,
544+
#if LCD_RGB_OPTIMUM_FB_SIZE
545+
attr, rgb_bus_attr,
546+
#endif
536547
locals_dict, (mp_obj_dict_t *)&mp_lcd_bus_locals_dict
537548
);
549+
538550
#else
539551
#include "../common_src/rgb_bus.c"
540552

0 commit comments

Comments
 (0)