diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_2d.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_2d.h index 36275b15ea..8844f5040b 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_2d.h +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_2d.h @@ -30,8 +30,8 @@ extern "C" /// @cond HIDDEN_SYMBOLS typedef struct { - UINT32 PatternA; - UINT32 PatternB; + uint32_t PatternA; + uint32_t PatternB; } MONOPATTERN; #define COLOR_KEY 0xFF000000 @@ -169,7 +169,7 @@ void ge2dSpriteBltx_ScreenRop(int x, int y, int sprite_sx, int sprite_sy, int wi void ge2dColorExpansionBlt(int x, int y, int width, int height, int fore_color, int back_color, int opt, void *buf); void ge2dHostColorExpansionBlt(int x, int y, int width, int height, int fore_color, int back_color, int opt, void *buf); void ge2dInitMonoPattern(int opt, int fore_color, int back_color); -void ge2dInitMonoInputPattern(UINT32 PatternA, UINT32 PatternB, int fore_color, int back_color); +void ge2dInitMonoInputPattern(uint32_t PatternA, uint32_t PatternB, int fore_color, int back_color); void ge2dInitColorPattern(int patformat, void *patdata); void ge2dFont_PutChar(int x, int y, char asc_code, int fore_color, int back_color, int draw_mode, int font_id); void ge2dFont_PutString(int x, int y, char *str, int fore_color, int back_color, int draw_mode, int font_id); diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h index bffcdcd589..bf05c3f9a9 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h +++ b/bsp/nuvoton/libraries/n9h30/Driver/Include/nu_lcd.h @@ -139,6 +139,8 @@ extern "C" #define VA_SCALE_INTERPOLATION (0) /*!< Scale mode is interpolation */ #define VA_SCALE_DUPLICATION (1<<15) /*!< Scale mode is duplication */ +#pragma anon_unions + typedef enum va_hcmode_e { HC_MODE0, /*!< 32X32X2bpp 4 color */ @@ -173,6 +175,7 @@ typedef struct #define DIS_PANEL_ILI9341_MPU80 1 #define DIS_LSA40AT9001 2 #define DIS_PANEL_FW070TFT 3 +#define DIS_PANEL_FW043TFT 4 typedef struct { uint32_t u32DevWidth; /*!< Panel width */ @@ -184,11 +187,62 @@ typedef struct uint32_t u32MPU_Mode; /*!< MPU mode */ uint32_t u32DisplayColors; /*!< Display colors */ uint32_t u32DevType; /*!< Type of display panel */ - uint32_t u32Reg_CRTCSIZE; /*!< CRTCSIZE register value */ - uint32_t u32Reg_CRTCDEND; /*!< CRTCDEND register value */ - uint32_t u32Reg_CRTCHR; /*!< CRTCHR register value */ - uint32_t u32Reg_CRTCHSYNC; /*!< CRTCHSYNC register value */ - uint32_t u32Reg_CRTCVR; /*!< CRTCVR register value */ + union + { + uint32_t u32Reg_CRTCSIZE; /*!< CRTCSIZE register value */ + struct + { + uint32_t HTT: 11; /*!< Horizontal Total Pixels */ + uint32_t : 5; + uint32_t VTT: 11; /*!< Vertical Total Scan Lines */ + uint32_t : 5; + } sCRTCSIZE; + }; + union + { + uint32_t u32Reg_CRTCDEND; /*!< CRTCDEND register value */ + struct + { + uint32_t HDEND: 11; /*!< Horizontal Display Enable End */ + uint32_t : 5; + uint32_t VDEND: 11; /*!< Vertical Display Enable End */ + uint32_t : 5; + } sCRTCDEND; + }; + union + { + uint32_t u32Reg_CRTCHR; /*!< CRTCHR register value */ + struct + { + uint32_t HRS: 11; /*!< Internal Horizontal Retrace Start Timing */ + uint32_t : 5; + uint32_t HRE: 11; /*!< Internal Horizontal Retrace End Low */ + uint32_t : 5; + } sCRTCHR; + }; + union + { + uint32_t u32Reg_CRTCHSYNC; /*!< CRTCHSYNC register value */ + struct + { + uint32_t HSYNC_S: 11; /*!< Horizontal Sync Start Timing */ + uint32_t : 5; + uint32_t HSYNC_E: 11; /*!< Horizontal Sync End Timing */ + uint32_t : 3; + uint32_t HSYNC_SHIFT: 2; /*!< Hsync Signal Adjustment For Multi-Cycles Per Pixel Mode Of Sync-Based Unipac-LCD */ + } sCRTCHSYNC; + }; + union + { + uint32_t u32Reg_CRTCVR; /*!< CRTCVR register value */ + struct + { + uint32_t VRS: 11; /*!< Vertical Internal Retrace Start Timing */ + uint32_t : 5; + uint32_t VRE: 11; /*!< Vertical Internal Retrace End Low */ + uint32_t : 5; + } sCRTCVR; + }; } VPOST_T; #define LCM_ERR_ID 0xFFFF0400 /*!< LCM library ID */ diff --git a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c index 423d03ec56..d71d110096 100644 --- a/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c +++ b/bsp/nuvoton/libraries/n9h30/Driver/Source/nu_lcd.c @@ -103,8 +103,74 @@ static VPOST_T DEF_FW070TFT = 0x020001f6 /*!< CRTCVR register value */ }; +#define FW043TFT_WIDTH 480 /*!< XRES */ +#define FW043TFT_HEIGHT 272 /*!< YRES */ +#define FW043TFT_MARGIN_LEFT 30 /*!< HBP (Horizontal Back Porch) */ +#define FW043TFT_MARGIN_RIGHT 5 /*!< HFP (Horizontal Front Porch) */ +#define FW043TFT_MARGIN_UPPER 2 /*!< VBP (Vertical Back Porch) */ +#define FW043TFT_MARGIN_LOWER 27 /*!< VFP (Vertical Front Porch) */ +#define FW043TFT_HSYNC_LEN 41 /*!< HPW (HSYNC plus width) */ +#define FW043TFT_VSYNC_LEN 10 /*!< VPW (VSYNC width) */ +static VPOST_T DEF_FW043TFT = +{ + FW043TFT_WIDTH, /*!< Panel width */ + FW043TFT_HEIGHT, /*!< Panel height */ + 0, /*!< MPU command line low indicator */ + 0, /*!< MPU command width */ + 0, /*!< MPU bus width */ + VPOSTB_DATA16or18, /*!< Display bus width */ + 0, /*!< MPU mode */ + VPOSTB_COLORTYPE_16M, /*!< Display colors */ + VPOSTB_DEVICE_SYNC_HIGHCOLOR, /*!< Type of display panel */ + + .sCRTCSIZE = + { + /*!< Horizontal Total */ + .HTT = FW043TFT_MARGIN_LEFT + FW043TFT_WIDTH + FW043TFT_MARGIN_RIGHT, + + /*!< Vertical Total */ + .VTT = FW043TFT_MARGIN_UPPER + FW043TFT_HEIGHT + FW043TFT_MARGIN_LOWER, + }, + .sCRTCDEND = + { + /*!< Horizontal Display Enable End */ + .HDEND = FW043TFT_WIDTH, + + /*!< Vertical Display Enable End */ + .VDEND = FW043TFT_HEIGHT, + }, + .sCRTCHR = + { + /*!< Internal Horizontal Retrace Start Timing */ + .HRS = FW043TFT_WIDTH + 1, + + /*!< Internal Horizontal Retrace End Low */ + .HRE = FW043TFT_WIDTH + 5, + }, + .sCRTCHSYNC = + { + /*!< Horizontal Sync Start Timing */ + .HSYNC_S = FW043TFT_WIDTH + FW043TFT_MARGIN_LEFT, + + /*!< Horizontal Sync End Timing */ + .HSYNC_E = FW043TFT_WIDTH + FW043TFT_MARGIN_LEFT + FW043TFT_HSYNC_LEN, + + /*!< Hsync Signal Adjustment For Multi-Cycles Per Pixel Mode Of Sync-Based Unipac-LCD */ + .HSYNC_SHIFT = 0, + }, + .sCRTCVR = + { + /*!< Vertical Internal Retrace Start Timing */ + .VRS = FW043TFT_HEIGHT + FW043TFT_MARGIN_UPPER, + + /*!< Vertical Internal Retrace End Low */ + .VRE = FW043TFT_HEIGHT + FW043TFT_MARGIN_UPPER + FW043TFT_VSYNC_LEN, + } +}; + + /* LCD build-in support list */ -static VPOST_T *DisplayDevList[4] = {&DEF_E50A2V1, &DEF_ILI9341_MPU80, &DEF_LSA40AT9001, &DEF_FW070TFT}; +static VPOST_T *DisplayDevList[5] = {&DEF_E50A2V1, &DEF_ILI9341_MPU80, &DEF_LSA40AT9001, &DEF_FW070TFT, &DEF_FW043TFT}; static VPOST_T curDisplayDev; static OSDFORMATEX curOSDDev = {0}; static LCDFORMATEX curVADev = {0}; diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig b/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig index 54ba33049a..7b898c79b5 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/Kconfig @@ -464,13 +464,16 @@ config SOC_SERIES_N9H30 prompt "Select Supported LCM panel" default LCM_USING_FW070TFT config LCM_USING_E50A2V1 - bool "LCM_E50A2V1(800x480x2)" + bool "LCM_E50A2V1(800x480-RGB565)" config LCM_USING_LSA40AT9001 - bool "LCM_LSA40AT9001(800x600x2)" + bool "LCM_LSA40AT9001(800x600-RGB565)" config LCM_USING_FW070TFT - bool "LCM_FW070TFT(800x480x4)" + bool "LCM_FW070TFT(800x480-RGB888)" + + config LCM_USING_FW043TFT + bool "LCM_FW043TFT(480x272-RGB888)" endchoice @@ -480,6 +483,7 @@ config SOC_SERIES_N9H30 default 2 if LCM_USING_LSA40AT9001 default 3 if LCM_USING_FW070TFT + default 4 if LCM_USING_FW043TFT config LCM_USING_BPP int @@ -487,6 +491,7 @@ config SOC_SERIES_N9H30 default 2 if LCM_USING_LSA40AT9001 default 4 if LCM_USING_FW070TFT + default 4 if LCM_USING_FW043TFT config BSP_USING_VPOST_OSD bool "Enable VPOST OSD layer" diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c index 5896a9b962..fb1f4433cf 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_adc_touch.c @@ -29,7 +29,21 @@ typedef nu_adc_touch *nu_adc_touch_t; static nu_adc_touch s_NuAdcTouch = {0}; #define DEF_CALDATA_LENGTH 7 -static int cal_data_a[DEF_CALDATA_LENGTH] = { 13230, -66, -1161952, -85, 8600, -1636996, 65536 }; + +#if defined(LCM_USING_FW043TFT) + #define LCM_WIDTH 480 + #define LCM_HEIGHT 272 + static int cal_data_a[DEF_CALDATA_LENGTH] = { 8824, -34, -2261272, -70, -6302, 21805816, 65536 }; +#else + #define LCM_WIDTH 800 + #define LCM_HEIGHT 480 + #if defined(LCM_USING_FW070TFT) + static int cal_data_a[DEF_CALDATA_LENGTH] = { 13230, -66, -1161952, -85, 8600, -1636996, 65536 }; + #else + static int cal_data_a[DEF_CALDATA_LENGTH] = { 1, 0, 0, 0, 1, 0, 1 }; + #endif +#endif + static const int cal_zero[DEF_CALDATA_LENGTH] = { 1, 0, 0, 0, 1, 0, 1 }; static void nu_adc_touch_cal(int *sumx, int *sumy) @@ -152,8 +166,8 @@ int rt_hw_adc_touch_init(void) s_NuAdcTouch.dev.info.type = RT_TOUCH_TYPE_RESISTANCE; s_NuAdcTouch.dev.info.vendor = RT_TOUCH_VENDOR_UNKNOWN; s_NuAdcTouch.dev.info.point_num = 1; - s_NuAdcTouch.dev.info.range_x = 800; - s_NuAdcTouch.dev.info.range_x = 480; + s_NuAdcTouch.dev.info.range_x = LCM_WIDTH; + s_NuAdcTouch.dev.info.range_y = LCM_HEIGHT; s_NuAdcTouch.dev.ops = &touch_ops; @@ -189,11 +203,11 @@ static void adc_touch_entry(void *parameter) result = rt_device_set_rx_indicate(pdev, adc_touch_rx_callback); RT_ASSERT(result == RT_EOK); - max_range = 800; + max_range = LCM_WIDTH; result = rt_device_control(pdev, RT_TOUCH_CTRL_SET_X_RANGE, (void *)&max_range); RT_ASSERT(result == RT_EOK); - max_range = 480; + max_range = LCM_HEIGHT; result = rt_device_control(pdev, RT_TOUCH_CTRL_SET_Y_RANGE, (void *)&max_range); RT_ASSERT(result == RT_EOK); diff --git a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c index b25eab57ec..398596ef13 100644 --- a/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c +++ b/bsp/nuvoton/libraries/n9h30/rtt_port/drv_vpost.c @@ -22,7 +22,7 @@ /* Private typedef --------------------------------------------------------------*/ -#define DEF_VPOST_BUFFER_NUMBER 2 +#define DEF_VPOST_BUFFER_NUMBER 3 typedef enum { @@ -157,12 +157,12 @@ static rt_err_t vpost_layer_control(rt_device_t dev, int cmd, void *args) } break; - /* FBIO_PANDISPLAY + WAIT_VSYNC Mechanism */ - case RTGRAPHIC_CTRL_RECT_UPDATE: + case RTGRAPHIC_CTRL_PAN_DISPLAY: { if (args != RT_NULL) { uint8_t *pu8BufPtr = (uint8_t *)args; + g_u32VSyncLastCommit = g_u32VSyncBlank; /* Pan display */ @@ -182,20 +182,27 @@ static rt_err_t vpost_layer_control(rt_device_t dev, int cmd, void *args) return -RT_ERROR; } - /*Wait sync*/ - while (g_u32VSyncLastCommit == g_u32VSyncBlank) - { - rt_completion_init(&vsync_wq); - rt_completion_wait(&vsync_wq, RT_TICK_PER_SECOND / 60); - } } else return -RT_ERROR; } break; + case RTGRAPHIC_CTRL_WAIT_VSYNC: + { + if (args != RT_NULL) + g_u32VSyncLastCommit = g_u32VSyncBlank+1; + + if (g_u32VSyncLastCommit >= g_u32VSyncBlank) + { + rt_completion_init(&vsync_wq); + rt_completion_wait(&vsync_wq, RT_TICK_PER_SECOND / 60); + } + } + break; + default: - break; + return -RT_ERROR; } return RT_EOK; @@ -254,8 +261,19 @@ int rt_hw_vpost_init(void) VPOST_T *psVpostLcmInst = vpostLCMGetInstance(VPOST_USING_LCD_IDX); RT_ASSERT(psVpostLcmInst != RT_NULL); - /* LCD clock is selected from UPLL and divide to 20MHz */ - outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0xff1f) | 0xE18); + if ( (psVpostLcmInst->u32DevWidth * psVpostLcmInst->u32DevHeight) > (480*272) ) + { + /* LCD clock is selected from UPLL and divide to 20MHz */ + outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0xff1f) | 0xE18); + + /* LCD clock is selected from UPLL and divide to 30MHz */ + //outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0xff1f) | 0x918); + } + else + { + /* LCD clock is selected from UPLL and divide to 10MHz */ + outpw(REG_CLK_DIVCTL1, (inpw(REG_CLK_DIVCTL1) & ~0xff1f) | 0xE19); + } /* Initial LCM */ vpostLCMInit(VPOST_USING_LCD_IDX); diff --git a/bsp/nuvoton/nk-980iot/applications/lvgl/lv_conf.h b/bsp/nuvoton/nk-980iot/applications/lvgl/lv_conf.h index b89513bc70..9c2479dc5c 100644 --- a/bsp/nuvoton/nk-980iot/applications/lvgl/lv_conf.h +++ b/bsp/nuvoton/nk-980iot/applications/lvgl/lv_conf.h @@ -11,20 +11,18 @@ #ifndef LV_CONF_H #define LV_CONF_H - #define LV_USE_PERF_MONITOR 1 #define LV_COLOR_DEPTH 16 #define LV_HOR_RES_MAX (320) #define LV_VER_RES_MAX (240) - -#define LV_USE_DEMO_RTT_MUSIC 1 -#define LV_USE_DEMO_MUSIC 1 #define LV_FONT_MONTSERRAT_12 1 #define LV_FONT_MONTSERRAT_16 1 -#define LV_DEMO_MUSIC_AUTO_PLAY 1 +#define LV_USE_DEMO_RTT_MUSIC 1 #define LV_DEMO_RTT_MUSIC_AUTO_PLAY 1 +#define LV_DISP_DEF_REFR_PERIOD 16 + //#define CONFIG_LV_LOG_LEVEL LV_LOG_LEVEL_TRACE #endif diff --git a/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_conf.h b/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_conf.h index 9b96e21b8d..cb73e49358 100644 --- a/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_conf.h +++ b/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_conf.h @@ -19,13 +19,12 @@ #define LV_HOR_RES_MAX (800) #define LV_VER_RES_MAX (480) - -#define LV_USE_DEMO_RTT_MUSIC 1 -#define LV_USE_DEMO_MUSIC 1 #define LV_FONT_MONTSERRAT_12 1 #define LV_FONT_MONTSERRAT_16 1 -#define LV_DEMO_MUSIC_AUTO_PLAY 1 +#define LV_USE_DEMO_RTT_MUSIC 1 #define LV_DEMO_RTT_MUSIC_AUTO_PLAY 1 +//#define LV_DISP_DEF_REFR_PERIOD 16 + //#define CONFIG_LV_LOG_LEVEL LV_LOG_LEVEL_TRACE #endif diff --git a/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c b/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c index 51615b09b7..193c9fddc3 100644 --- a/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c +++ b/bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c @@ -8,6 +8,7 @@ * 2021-12-17 Wayne The first version */ #include +#include "nu_2d.h" #define LOG_TAG "lvgl.disp" #define DBG_ENABLE @@ -22,50 +23,112 @@ static rt_device_t lcd_device = 0; static struct rt_device_graphic_info info; static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/ -extern void ge2dInit(int bpp, int width, int height, void *destination); -extern void ge2dSpriteBlt_Screen(int destx, int desty, int sprite_width, int sprite_height, void *buf); -extern int ge2dBitblt_SetAlphaMode(int opt, int ks, int kd); -extern void ge2dSpriteBltx_Screen(int x, int y, int sprite_sx, int sprite_sy, int width, int height, int sprite_width, int sprite_height, void *buf); -extern void ge2dClip_SetClip(int x1, int y1, int x2, int y2); -extern void ge2dFill_Solid_RGB565(int dx, int dy, int width, int height, int color); -extern void ge2dFill_Solid(int dx, int dy, int width, int height, int color); - -static void lcd_fb_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) +static void nu_flush_direct(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { - /* Use ping-pong buffer updating without memory-copy. */ - rt_device_control(lcd_device, RTGRAPHIC_CTRL_RECT_UPDATE, color_p); + lv_disp_t *psDisp = _lv_refr_get_disp_refreshing(); + void *pvDstReDraw; + + /* Use PANDISPLAY */ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_PAN_DISPLAY, color_p); + + /* Need to do on-/off- screen buffer synchronization. Here, we do a source-copying using GE2D engine. */ + if (disp_drv->draw_buf->buf1 == color_p) + pvDstReDraw = disp_drv->draw_buf->buf2; + else + pvDstReDraw = disp_drv->draw_buf->buf1; + + // Enter GE2D -> + ge2dInit(sizeof(lv_color_t) * 8, info.width, info.height, pvDstReDraw); + ge2dBitblt_SetAlphaMode(-1, 0, 0); + ge2dBitblt_SetDrawMode(-1, 0, 0); + ge2dSpriteBlt_Screen(0, 0, info.width, info.height, (void *)color_p); + // -> Leave GE2D + + /* WAIT_VSYNC */ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_WAIT_VSYNC, RT_NULL); lv_disp_flush_ready(disp_drv); } -void ge2d_fill_cb(struct _lv_disp_drv_t *disp_drv, lv_color_t *dest_buf, lv_coord_t dest_width, - const lv_area_t *fill_area, lv_color_t color) +static void nu_flush_full_refresh(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { - int32_t act_x1 = fill_area->x1 < 0 ? 0 : fill_area->x1; - int32_t act_y1 = fill_area->y1 < 0 ? 0 : fill_area->y1; - int32_t act_x2 = fill_area->x2 > info.width - 1 ? info.width - 1 : fill_area->x2; - int32_t act_y2 = fill_area->y2 > info.height - 1 ? info.height - 1 : fill_area->y2; - int32_t fill_area_w = act_x2 - act_x1 + 1; - int32_t fill_area_h = act_y2 - act_y1 + 1; + /* Use PANDISPLAY+WAIT_VSYNC without H/W copying. */ + rt_device_control(lcd_device, RTGRAPHIC_CTRL_PAN_DISPLAY, color_p); + rt_device_control(lcd_device, RTGRAPHIC_CTRL_WAIT_VSYNC, RT_NULL); - // Enter GE2D -> - ge2dInit(sizeof(lv_color_t) * 8, info.width, info.height, (void *)dest_buf); - ge2dClip_SetClip(act_x1, act_y1, act_x2, act_y2); - if (sizeof(lv_color_t) == 4) - { - ge2dFill_Solid(act_x1, act_y1, fill_area_w, fill_area_h, color.full); - } - else if (sizeof(lv_color_t) == 2) - { - ge2dFill_Solid_RGB565(act_x1, act_y1, fill_area_w, fill_area_h, color.full); - } - ge2dClip_SetClip(-1, 0, 0, 0); - // -> Leave GE2D + lv_disp_flush_ready(disp_drv); } -void lcd_perf_monitor(struct _lv_disp_drv_t *disp_drv, uint32_t time, uint32_t px) +static void nu_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p) { - rt_kprintf("Elapsed: %dms, Pixel: %d, Bytes:%d\n", time, px, px * sizeof(lv_color_t)); + int32_t flush_area_w = lv_area_get_width(area); + int32_t flush_area_h = lv_area_get_height(area); + + //rt_kprintf("[%s %08x] %dx%d %d %d %d %d\n", __func__, color_p, flush_area_w, flush_area_h, area->x1, area->y1, area->x2, area->y2 ); + + /* Update dirty region. */ + // Enter GE2D -> + ge2dInit(sizeof(lv_color_t) * 8, info.width, info.height, (void *)info.framebuffer); + ge2dBitblt_SetAlphaMode(-1, 0, 0); + ge2dBitblt_SetDrawMode(-1, 0, 0); + + ge2dSpriteBlt_Screen(area->x1, area->y1, flush_area_w, flush_area_h, (void *)color_p); + // -> Leave GE2D + + lv_disp_flush_ready(disp_drv); +} + + +static void nu_fill_cb(struct _lv_disp_drv_t *disp_drv, lv_color_t *dest_buf, lv_coord_t dest_width, + const lv_area_t *fill_area, lv_color_t color) +{ + int32_t fill_area_w = lv_area_get_width(fill_area); + int32_t fill_area_h = lv_area_get_height(fill_area); + + //rt_kprintf("[%s %08x] %dx%d %d %d %d %d\n", __func__, dest_buf, fill_area_w, fill_area_h, fill_area->x1, fill_area->y1, fill_area->x2, fill_area->y2 ); + + if (lv_area_get_size(fill_area) < 3600) + { + /*Software filling*/ + int y; + lv_color_t *disp_buf_first = dest_buf + dest_width * fill_area->y1 + fill_area->x1; + for (y = 0; y < fill_area_h; y++) + { + lv_color_fill(disp_buf_first, color, fill_area_w); + disp_buf_first += dest_width; + } + } + else + { + /*Hardware filling*/ + if (disp_drv->direct_mode || disp_drv->full_refresh) + { + // Enter GE2D -> + ge2dInit(sizeof(lv_color_t) * 8, info.width, info.height, (void *)dest_buf); + } + else + { + // Enter GE2D -> + ge2dInit(sizeof(lv_color_t) * 8, fill_area_w, fill_area_h, (void *)dest_buf); + } + + ge2dClip_SetClip(fill_area->x1, fill_area->y1, fill_area->x2, fill_area->y2); + if (sizeof(lv_color_t) == 4) + { + ge2dFill_Solid(fill_area->x1, fill_area->y1, fill_area_w, fill_area_h, color.full); + } + else if (sizeof(lv_color_t) == 2) + { + ge2dFill_Solid_RGB565(fill_area->x1, fill_area->y1, fill_area_w, fill_area_h, color.full); + } + ge2dClip_SetClip(-1, 0, 0, 0); + // -> Leave GE2D + } +} + +void nu_perf_monitor(struct _lv_disp_drv_t *disp_drv, uint32_t time, uint32_t px) +{ + rt_kprintf("Elapsed: %dms, Pixel: %d, Bytes:%d, %d%\n", time, px, px * sizeof(lv_color_t), px * 100 / disp_drv->draw_buf->size); } void lv_port_disp_init(void) @@ -73,6 +136,7 @@ void lv_port_disp_init(void) rt_err_t result; void *buf_1 = RT_NULL; void *buf_2 = RT_NULL; + uint32_t u32FBSize; lcd_device = rt_device_find("lcd"); if (lcd_device == 0) @@ -93,9 +157,35 @@ void lv_port_disp_init(void) RT_ASSERT(info.bits_per_pixel == 8 || info.bits_per_pixel == 16 || info.bits_per_pixel == 24 || info.bits_per_pixel == 32); - buf_1 = (void *)info.framebuffer; - buf_2 = (void *)((uint32_t)buf_1 + info.height * info.width * info.bits_per_pixel / 8); - rt_kprintf("LVGL: Use two buffers - buf_1@%08x, buf_2@%08x\n", buf_1, buf_2); + lv_disp_drv_init(&disp_drv); /*Basic initialization*/ + + /*Set the resolution of the display*/ + disp_drv.hor_res = info.width; + disp_drv.ver_res = info.height; + //disp_drv.full_refresh = 1; + disp_drv.direct_mode = 1; + u32FBSize = info.height * info.width * (info.bits_per_pixel / 8); + + if (disp_drv.full_refresh || disp_drv.direct_mode) + { + buf_1 = (void *)info.framebuffer; + buf_2 = (void *)((uint32_t)buf_1 + u32FBSize); + rt_kprintf("LVGL: Two screen-sized buffers(%s) - buf_1@%08x, buf_2@%08x\n", (disp_drv.full_refresh == 1) ? "full_refresh" : "direct_mode", buf_1, buf_2); + + if (disp_drv.direct_mode) + disp_drv.flush_cb = nu_flush_direct; + else + disp_drv.flush_cb = nu_flush_full_refresh; + } + else + { + buf_1 = (void *)(((uint32_t)info.framebuffer) + u32FBSize); + buf_2 = (void *)((uint32_t)buf_1 + u32FBSize); + rt_kprintf("LVGL: Two screen-sized buffers - buf_1@%08x, buf_2@%08x\n", buf_1, buf_2); + rt_device_control(lcd_device, RTGRAPHIC_CTRL_PAN_DISPLAY, info.framebuffer); + + disp_drv.flush_cb = nu_flush; + } /*Initialize `disp_buf` with the buffer(s).*/ lv_disp_draw_buf_init(&disp_buf, buf_1, buf_2, info.width * info.height); @@ -107,24 +197,14 @@ void lv_port_disp_init(void) return; } - lv_disp_drv_init(&disp_drv); /*Basic initialization*/ - - /*Set the resolution of the display*/ - disp_drv.hor_res = info.width; - disp_drv.ver_res = info.height; - disp_drv.full_refresh = 1; - /*Set a display buffer*/ disp_drv.draw_buf = &disp_buf; - /*Write the internal buffer (draw_buf) to the display*/ - disp_drv.flush_cb = lcd_fb_flush; - /*Fill a memory with a color (GPU only)*/ - disp_drv.gpu_fill_cb = ge2d_fill_cb; + disp_drv.gpu_fill_cb = nu_fill_cb; - /* Called after every refresh cycle to tell the rendering and flushing time + the number of flushed pixels */ - //disp_drv.monitor_cb = lcd_perf_monitor; + /*Called after every refresh cycle to tell the rendering and flushing time + the number of flushed pixels*/ + //disp_drv.monitor_cb = nu_perf_monitor; /*Finally register the driver*/ lv_disp_drv_register(&disp_drv); diff --git a/include/rtdef.h b/include/rtdef.h index c22c20beee..b31bd1e3f8 100644 --- a/include/rtdef.h +++ b/include/rtdef.h @@ -1098,6 +1098,8 @@ struct rt_device_blk_sectors #define RTGRAPHIC_CTRL_GET_BRIGHTNESS 7 #define RTGRAPHIC_CTRL_GET_MODE 8 #define RTGRAPHIC_CTRL_GET_STATUS 9 +#define RTGRAPHIC_CTRL_PAN_DISPLAY 10 +#define RTGRAPHIC_CTRL_WAIT_VSYNC 11 /* graphic deice */ enum