Browse Source

Update LVGLv81 porting.

1. Add RTGRAPHIC_CTRL_PAN_DISPLAY and RTGRAPHIC_CTRL_WAIT_VSYNC control command.
2. Add calibration data of 480x272 ADC touching.
3. Add 480x272 LCD panel menu option and driver.
4. Update lv_conf.h.
Wayne Lin 3 years ago
parent
commit
e8f4208bb2

+ 3 - 3
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);

+ 59 - 5
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 */

+ 67 - 1
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};

+ 8 - 3
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"

+ 19 - 5
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);
 

+ 30 - 12
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);

+ 3 - 5
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

+ 3 - 4
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

+ 124 - 44
bsp/nuvoton/nk-n9h30/applications/lvgl/lv_port_disp.c

@@ -8,6 +8,7 @@
  * 2021-12-17     Wayne        The first version
  */
 #include <lvgl.h>
+#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 nu_flush_direct(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *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);
+}
 
-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_full_refresh(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);
+    /* 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);
 
     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(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;
+    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 *)dest_buf);
-    ge2dClip_SetClip(act_x1, act_y1, act_x2, act_y2);
-    if (sizeof(lv_color_t) == 4)
+    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)
     {
-        ge2dFill_Solid(act_x1, act_y1, fill_area_w, fill_area_h, color.full);
+        /*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 if (sizeof(lv_color_t) == 2)
+    else
     {
-        ge2dFill_Solid_RGB565(act_x1, act_y1, fill_area_w, fill_area_h, color.full);
+        /*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
     }
-    ge2dClip_SetClip(-1, 0, 0, 0);
-    // -> Leave GE2D
 }
 
-void lcd_perf_monitor(struct _lv_disp_drv_t *disp_drv, uint32_t time, uint32_t px)
+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\n", time, px, px * sizeof(lv_color_t));
+    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);

+ 2 - 0
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