فهرست منبع

add:qspi-lcd全脚本适配,不再添加新的内置配置

alienwalker 8 ماه پیش
والد
کامیت
5a83155c7b

+ 10 - 3
components/lcd/luat_lcd.c

@@ -153,9 +153,11 @@ LUAT_WEAK int luat_lcd_init_default(luat_lcd_conf_t* conf) {
     if (conf->pin_pwr != LUAT_GPIO_NONE) {
     if (conf->pin_pwr != LUAT_GPIO_NONE) {
         luat_gpio_set(conf->pin_pwr, Luat_GPIO_LOW);
         luat_gpio_set(conf->pin_pwr, Luat_GPIO_LOW);
     }
     }
-	if (conf->opts->user_ctrl_init)
-	{
-		conf->opts->user_ctrl_init(conf);
+	if (conf->opts->user_ctrl_init) {
+		int res = conf->opts->user_ctrl_init(conf);
+		if (res > 0) {
+			goto INIT_NOT_DONE;
+		}
 		goto INIT_DONE;
 		goto INIT_DONE;
 	}
 	}
     luat_gpio_set(conf->pin_rst, Luat_GPIO_LOW);
     luat_gpio_set(conf->pin_rst, Luat_GPIO_LOW);
@@ -184,6 +186,7 @@ LUAT_WEAK int luat_lcd_init_default(luat_lcd_conf_t* conf) {
     luat_lcd_display_on(conf);
     luat_lcd_display_on(conf);
 INIT_DONE:
 INIT_DONE:
     conf->is_init_done = 1;
     conf->is_init_done = 1;
+INIT_NOT_DONE:
     for (size_t i = 0; i < LUAT_LCD_CONF_COUNT; i++){
     for (size_t i = 0; i < LUAT_LCD_CONF_COUNT; i++){
         if (lcd_confs[i] == NULL) {
         if (lcd_confs[i] == NULL) {
             lcd_confs[i] = conf;
             lcd_confs[i] = conf;
@@ -622,6 +625,10 @@ LUAT_WEAK int luat_lcd_qspi_config(luat_lcd_conf_t* conf, luat_lcd_qspi_conf_t *
 LUAT_WEAK int luat_lcd_qspi_auto_flush_on_off(luat_lcd_conf_t* conf, uint8_t on_off) {
 LUAT_WEAK int luat_lcd_qspi_auto_flush_on_off(luat_lcd_conf_t* conf, uint8_t on_off) {
     return -1;
     return -1;
 }
 }
+
+LUAT_WEAK uint8_t luat_lcd_qspi_is_no_ram(luat_lcd_conf_t* conf) {
+    return 0;
+}
 LUAT_WEAK int luat_lcd_run_api_in_service(luat_lcd_api api, void *param, uint32_t param_len) {
 LUAT_WEAK int luat_lcd_run_api_in_service(luat_lcd_api api, void *param, uint32_t param_len) {
     return -1;
     return -1;
 };
 };

+ 5 - 4
components/lcd/luat_lcd.h

@@ -64,12 +64,12 @@ enum{
 
 
 typedef struct
 typedef struct
 {
 {
-	uint8_t write_4line_cmd;
+	uint8_t write_4line_cmd;  //address 1线 data4线
 	uint8_t vsync_reg;
 	uint8_t vsync_reg;
 	uint8_t hsync_cmd;
 	uint8_t hsync_cmd;
 	uint8_t hsync_reg;
 	uint8_t hsync_reg;
-	uint8_t write_1line_cmd;
-	uint8_t write_4line_data;
+	uint8_t write_1line_cmd;	//cmd 1线 param 1线
+	uint8_t write_4line_data;	//address data都是4线
 }luat_lcd_qspi_conf_t;
 }luat_lcd_qspi_conf_t;
 
 
 typedef struct luat_lcd_conf {
 typedef struct luat_lcd_conf {
@@ -146,7 +146,7 @@ extern luat_lcd_opts_t lcd_opts_st7796;
 extern luat_lcd_opts_t lcd_opts_nv3037;
 extern luat_lcd_opts_t lcd_opts_nv3037;
 extern luat_lcd_opts_t lcd_opts_h050iwv;
 extern luat_lcd_opts_t lcd_opts_h050iwv;
 extern luat_lcd_opts_t lcd_opts_jd9261t_inited;
 extern luat_lcd_opts_t lcd_opts_jd9261t_inited;
-extern luat_lcd_opts_t lcd_opts_jd9261t;
+//extern luat_lcd_opts_t lcd_opts_jd9261t;
 extern luat_lcd_opts_t lcd_opts_sh8601z;
 extern luat_lcd_opts_t lcd_opts_sh8601z;
 
 
 static inline luat_color_t color_swap(luat_color_t color) {
 static inline luat_color_t color_swap(luat_color_t color) {
@@ -251,6 +251,7 @@ int luat_lcd_stop_show_camera(void *camera_info);
 
 
 int luat_lcd_qspi_config(luat_lcd_conf_t* conf, luat_lcd_qspi_conf_t *qspi_config);
 int luat_lcd_qspi_config(luat_lcd_conf_t* conf, luat_lcd_qspi_conf_t *qspi_config);
 int luat_lcd_qspi_auto_flush_on_off(luat_lcd_conf_t* conf, uint8_t on_off);
 int luat_lcd_qspi_auto_flush_on_off(luat_lcd_conf_t* conf, uint8_t on_off);
+uint8_t luat_lcd_qspi_is_no_ram(luat_lcd_conf_t* conf);
 typedef void (*luat_lcd_api)(void *param, uint32_t param_len);
 typedef void (*luat_lcd_api)(void *param, uint32_t param_len);
 int luat_lcd_run_api_in_service(luat_lcd_api api, void *param, uint32_t param_len);
 int luat_lcd_run_api_in_service(luat_lcd_api api, void *param, uint32_t param_len);
 
 

+ 19 - 0
components/lcd/luat_lcd_custom.c

@@ -12,3 +12,22 @@ luat_lcd_opts_t lcd_opts_custom = {
     .name = "custom",
     .name = "custom",
 };
 };
 
 
+static int lcd_user_ctrl_init(luat_lcd_conf_t* conf)
+{
+	if (LUAT_LCD_IM_QSPI_MODE == conf->interface_mode)
+	{
+		if (luat_lcd_qspi_is_no_ram(conf))
+		{
+			conf->opts->no_ram_mode = 1;
+		}
+	    luat_lcd_qspi_config(conf, NULL);	//必须在第一个命令发送前就准备好
+	}
+
+	return 1;
+}
+
+
+luat_lcd_opts_t lcd_opts_user_ctrl = {
+    .name = "user",
+	.user_ctrl_init = lcd_user_ctrl_init,
+};

+ 3 - 0
components/lcd/luat_lcd_jd9261t.c

@@ -57,6 +57,7 @@ luat_lcd_opts_t lcd_opts_jd9261t_inited = {
 	.user_ctrl_init = jd9261t_inited_init,
 	.user_ctrl_init = jd9261t_inited_init,
 };
 };
 
 
+#if 0
 typedef struct
 typedef struct
 {
 {
 	union
 	union
@@ -451,3 +452,5 @@ luat_lcd_opts_t lcd_opts_jd9261t = {
 	.no_ram_mode = 1,
 	.no_ram_mode = 1,
 	.user_ctrl_init = jd9261t_init,
 	.user_ctrl_init = jd9261t_init,
 };
 };
+
+#endif

+ 77 - 5
components/lcd/luat_lib_lcd.c

@@ -29,6 +29,7 @@ uint8_t u8g2_font_decode_get_unsigned_bits(u8g2_font_decode_t *f, uint8_t cnt);
 extern luat_color_t BACK_COLOR , FORE_COLOR ;
 extern luat_color_t BACK_COLOR , FORE_COLOR ;
 
 
 extern const luat_lcd_opts_t lcd_opts_custom;
 extern const luat_lcd_opts_t lcd_opts_custom;
+extern const luat_lcd_opts_t lcd_opts_user_ctrl;
 
 
 typedef struct lcd_reg {
 typedef struct lcd_reg {
   const char *name;
   const char *name;
@@ -68,10 +69,10 @@ static const lcd_reg_t lcd_regs[] = {
   {"st7701s",  &lcd_opts_st7701s},
   {"st7701s",  &lcd_opts_st7701s},
   {"st7701sn",  &lcd_opts_st7701sn},
   {"st7701sn",  &lcd_opts_st7701sn},
   {"sh8601z",  &lcd_opts_sh8601z},
   {"sh8601z",  &lcd_opts_sh8601z},
+  {"user",  &lcd_opts_user_ctrl},
   {"", NULL} // 最后一个必须是空字符串
   {"", NULL} // 最后一个必须是空字符串
 };
 };
 
 
-
 luat_lcd_conf_t *lcd_dft_conf = NULL;
 luat_lcd_conf_t *lcd_dft_conf = NULL;
 // static int dft_conf_lua_ref = 0;
 // static int dft_conf_lua_ref = 0;
 
 
@@ -538,14 +539,33 @@ static int l_lcd_inv_off(lua_State* L) {
 
 
 /*
 /*
 lcd命令
 lcd命令
-@api lcd.cmd(cmd)
-@int cmd
+@api lcd.cmd(cmd, param, param_len)
+@int lcd命令模式下的命令值
+@int/zbuff lcd命令模式下的参数值,如果只有1个参数,可以用int,如果有多个,使用zbuff传入
+@int 参数长度,如果上一个参数是int,则忽略长度
+@return boolean
 @usage
 @usage
 -- lcd命令
 -- lcd命令
 lcd.cmd(0x21)
 lcd.cmd(0x21)
+lcd.cmd(0x21)
 */
 */
 static int l_lcd_write_cmd(lua_State* L) {
 static int l_lcd_write_cmd(lua_State* L) {
-    int ret = lcd_write_cmd_data(lcd_dft_conf,(uint8_t)luaL_checkinteger(L, 1), NULL, 0);
+	uint8_t param;
+	uint32_t param_len = 0;
+	const uint8_t *data = NULL;
+	if (lua_isinteger(L, 2))
+	{
+		param = lua_tointeger(L, 2);
+		param_len = 1;
+		data = &param;
+	}
+	else if (lua_isuserdata(L, 2)) {
+        // zbuff
+        luat_zbuff_t* buff = ((luat_zbuff_t *)luaL_checkudata(L, 2, LUAT_ZBUFF_TYPE));
+        data = (const char*)buff->addr;
+        param_len = luaL_optinteger(L, 3, buff->used);
+    }
+    int ret = lcd_write_cmd_data(lcd_dft_conf,(uint8_t)luaL_checkinteger(L, 1), data, param_len);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 1;
     return 1;
 }
 }
@@ -1769,6 +1789,53 @@ static const int l_lcd_draw_utf8(lua_State *L) {
 }
 }
 #endif
 #endif
 
 
+/*
+硬件lcd qspi接口配置,需要在lcd.init前配置好
+@api lcd.qspi(1_wire_command, 1_wire_command, 1_wire_command_4_wire_data, 4_wire_command_4_wire_data, vsync_reg, hsync_cmd, hsync_reg)
+@int lcd命令模式下的qspi指令
+@int lcd数据模式下,1线地址,4线数据的qspi指令,
+@int lcd数据模式下,4线地址,4线数据的qspi指令,可以留空,如果存在,发送数据时优先使用这个模式
+@int 帧同步时的地址值,只有无ram的屏幕需要,如果能用0x2c发送数据则不需要这个参数
+@int 行同步时的指令,一般情况和命令模式下的指令一致,只有无ram的屏幕需要,如果能用0x2c发送数据则不需要这个参数
+@int 行同步时的地址值,只有无ram的屏幕需要,如果能用0x2c发送数据则不需要这个参数
+@return nil
+@usage
+-- sh8601z驱动ic所需的qspi配置
+lcd.qspi(0x02, 0x32, 0x12)
+-- jd9261t驱动ic所需的qspi配置
+lcd.qspi(0xde, 0xde, nil, 0x61, 0xde, 0x60)
+-- CO5300驱动ic所需的qspi配置
+lcd.qspi(0x02, 0x32, 0x12)
+*/
+static int l_lcd_qspi_config(lua_State* L)
+{
+	luat_lcd_qspi_conf_t qspi_config = {0};
+	qspi_config.write_1line_cmd = luaL_optinteger(L, 1, 0x02);
+	qspi_config.write_4line_cmd = luaL_optinteger(L, 2, 0x32);
+	qspi_config.write_4line_data = luaL_optinteger(L, 3, 0);
+	qspi_config.vsync_reg = luaL_optinteger(L, 4, 0);
+	qspi_config.hsync_cmd = luaL_optinteger(L, 5, 0);
+	qspi_config.hsync_reg = luaL_optinteger(L, 6, 0);
+	luat_lcd_qspi_config(NULL, &qspi_config);
+	return 0;
+}
+
+/*
+用户使用脚本初始化LCD完成后,必须调用本API
+@api lcd.user_done()
+@return nil
+*/
+static int l_lcd_user_ctrl_done(lua_State* L)
+{
+	lcd_dft_conf->is_init_done = 1;
+	if (LUAT_LCD_IM_QSPI_MODE == lcd_dft_conf->interface_mode) {
+		if (luat_lcd_qspi_is_no_ram(lcd_dft_conf)) {
+		    luat_lcd_qspi_auto_flush_on_off(lcd_dft_conf, 1);
+		}
+	}
+	return 0;
+}
+
 #include "rotable2.h"
 #include "rotable2.h"
 static const rotable_Reg_t reg_lcd[] =
 static const rotable_Reg_t reg_lcd[] =
 {
 {
@@ -1801,6 +1868,8 @@ static const rotable_Reg_t reg_lcd[] =
     { "setColor",   ROREG_FUNC(l_lcd_set_color)},
     { "setColor",   ROREG_FUNC(l_lcd_set_color)},
     { "draw",       ROREG_FUNC(l_lcd_draw)},
     { "draw",       ROREG_FUNC(l_lcd_draw)},
     { "rgb565",     ROREG_FUNC(l_lcd_rgb565)},
     { "rgb565",     ROREG_FUNC(l_lcd_rgb565)},
+	{ "qspi",		ROREG_FUNC(l_lcd_qspi_config)},
+	{ "user_done",		ROREG_FUNC(l_lcd_user_ctrl_done)},
 #ifdef LUAT_USE_UFONT
 #ifdef LUAT_USE_UFONT
     { "drawUTF8",   ROREG_FUNC(l_lcd_draw_utf8)},
     { "drawUTF8",   ROREG_FUNC(l_lcd_draw_utf8)},
 #endif
 #endif
@@ -1944,9 +2013,12 @@ static const rotable_Reg_t reg_lcd[] =
     { "WIRE_3_BIT_9_INTERFACE_II",  ROREG_INT(LUAT_LCD_IM_3_WIRE_9_BIT_INTERFACE_II)},
     { "WIRE_3_BIT_9_INTERFACE_II",  ROREG_INT(LUAT_LCD_IM_3_WIRE_9_BIT_INTERFACE_II)},
     //@const WIRE_4_BIT_8_INTERFACE_II 四线spi 8bit 模式II
     //@const WIRE_4_BIT_8_INTERFACE_II 四线spi 8bit 模式II
     { "WIRE_4_BIT_8_INTERFACE_II",  ROREG_INT(LUAT_LCD_IM_4_WIRE_8_BIT_INTERFACE_II)},
     { "WIRE_4_BIT_8_INTERFACE_II",  ROREG_INT(LUAT_LCD_IM_4_WIRE_8_BIT_INTERFACE_II)},
-    //@const DATA_2_LANE int 双通道模式
+    //@const DATA_2_LANE spi双通道模式
     { "DATA_2_LANE",                ROREG_INT(LUAT_LCD_IM_2_DATA_LANE)},
     { "DATA_2_LANE",                ROREG_INT(LUAT_LCD_IM_2_DATA_LANE)},
+	//@const QSPI_MODE QSPI模式
 	{ "QSPI_MODE",                ROREG_INT(LUAT_LCD_IM_QSPI_MODE)},
 	{ "QSPI_MODE",                ROREG_INT(LUAT_LCD_IM_QSPI_MODE)},
+	//@const 8080_MODE 8080模式
+	{ "8080_MODE",                ROREG_INT(LUAT_LCD_IM_8080_MODE)},
 	  {NULL, ROREG_INT(0)}
 	  {NULL, ROREG_INT(0)}
 };
 };
 
 

+ 20 - 0
luat/demo/lcd_qspi/co5300.lua

@@ -0,0 +1,20 @@
+-- 必须在task里用
+function co5300_init(lcd_cfg)
+    lcd.qspi(0x02, 0x32, 0x12)
+    lcd.init("user", lcd_cfg) 
+    gpio.set(lcd_cfg.pin_rst, 0)
+    sys.wait(300)
+    gpio.set(lcd_cfg.pin_rst, 1)
+    sys.wait(200)
+    lcd.cmd(0xfe, 0x00)
+    lcd.cmd(0xc4, 0x80)
+    lcd.cmd(0x3a, 0x55)
+    lcd.cmd(0x35, 0x00)
+    lcd.cmd(0x53, 0x20)
+    lcd.cmd(0x51, 0x7a)
+    lcd.cmd(0x63, 0xaa)
+    lcd.cmd(0x36, 0x00) --方向
+    lcd.wakeup()
+    sys.wait(200)
+    lcd.cmd(0x29)
+end

+ 12 - 0
luat/demo/lcd_qspi/jd9261t.lua

@@ -0,0 +1,12 @@
+-- 必须在task里用
+function jd9261t_init(lcd_cfg)
+    lcd.qspi(0xde, 0xde, nil, 0x61, 0xde, 0x60)
+    lcd.init("user", lcd_cfg) 
+    gpio.set(lcd_cfg.pin_rst, 0)
+    gpio.set(lcd_cfg.pin_pwr, 0)
+    sys.wait(5)
+    gpio.set(lcd_cfg.pin_rst, 1)
+    sys.wait(200)
+    lcd.cmd(0x36, 0x00) --方向
+    gpio.set(lcd_cfg.pin_pwr, 1)
+end

+ 46 - 0
luat/demo/lcd_qspi/main.lua

@@ -0,0 +1,46 @@
+PROJECT = "lcd_qspi"
+VERSION = "1.0.0"
+
+log.info("main", PROJECT, VERSION)
+
+require "co5300"
+require "jd9261t"
+require "sh8601z"
+
+sys.taskInit(function()
+
+    local test_cnt = 0
+    pm.ioVol(0, 3300)
+    gpio.setup(20,1)    --打开sh8601z LCD电源,根据板子实际情况修改
+    gpio.setup(16,1)    --打开jd9261t LCD电源,根据板子实际情况修改
+    gpio.setup(17,1)    --打开co5300 LCD电源,根据板子实际情况修改
+
+    co5300_init({port = lcd.HWID_0, pin_dc = -1, pin_pwr = -1, pin_rst = 36, w = 480, h = 480, interface_mode=lcd.QSPI_MODE,bus_speed=50000000, rb_swap = true})
+    -- jd9261t_init({port = lcd.HWID_0,pin_dc = -1, pin_pwr = 27, pin_rst = 36, w = 480,h = 480, interface_mode=lcd.QSPI_MODE, bus_speed=60000000,flush_rate=659,vbp=19,vfp=108,vs=2,rb_swap=true})
+    -- jd9261t_init({port = lcd.HWID_0,pin_dc = -1, pin_pwr = 27, pin_rst = 36, w = 540,h = 540, interface_mode=lcd.QSPI_MODE, bus_speed=80000000,flush_rate=600,vbp=10,vfp=108,vs=2,rb_swap=true})
+    -- jd9261t_init({port = lcd.HWID_0,pin_dc = -1, pin_pwr = 27, pin_rst = 36, w = 720,h = 720, interface_mode=lcd.QSPI_MODE, bus_speed=60000000,flush_rate=300,vbp=10,vfp=160,vs=2,rb_swap=true})
+    -- sh8601z_init({port = lcd.HWID_0, pin_dc = -1, pin_pwr = -1, pin_rst = 36, w = 368, h = 448, interface_mode=lcd.QSPI_MODE,bus_speed=80000000, rb_swap = true})
+    lcd.setupBuff(nil, false)
+    lcd.autoFlush(false)
+    lcd.user_done() --必须在初始化完成后,在正式显示之前
+    while true do 
+        lcd.clear()
+        log.info("wiki", "https://wiki.luatos.com/api/lcd.html")
+        log.info("lcd.drawLine", lcd.drawLine(20,20 + test_cnt * 10,150,20 + test_cnt * 10,0x001F))
+        log.info("lcd.drawRectangle", lcd.drawRectangle(20,40 + test_cnt * 10,120,70 + test_cnt * 10,0xF800))
+        log.info("lcd.drawCircle", lcd.drawCircle(50 + test_cnt * 10,50 + test_cnt * 10,20,0x0CE0))
+
+        lcd.flush()
+        test_cnt = test_cnt + 1
+        if test_cnt > 10 then
+            test_cnt = 0
+        end
+        sys.wait(3000)
+    end
+end)
+
+-- 用户代码已结束---------------------------------------------
+-- 结尾总是这一句
+sys.run()
+-- sys.run()之后后面不要加任何语句!!!!!
+

+ 27 - 0
luat/demo/lcd_qspi/sh8601z.lua

@@ -0,0 +1,27 @@
+-- 必须在task里用
+function sh8601z_init(lcd_cfg)
+    lcd.qspi(0x02, 0x32, 0x12)
+    lcd.init("user", lcd_cfg) 
+    gpio.set(lcd_cfg.pin_rst, 0)
+    sys.wait(20)
+    gpio.set(lcd_cfg.pin_rst, 1)
+    sys.wait(50)
+    lcd.wakeup()
+    sys.wait(100)
+    -- 演示一下用zbuff传参数,和下面的直接传参数是等效的
+    local param = zbuff.create(1)
+    param[0] = 0x00
+    lcd.cmd(0x36, param, 1) --方向
+    param[0] = 0x55
+    lcd.cmd(0x3a, param, 1)
+    param[0] = 0x20
+    lcd.cmd(0x53, param, 1)
+    param[0] = 0xff
+    lcd.cmd(0x51, param, 1)
+
+    -- lcd.cmd(0x36, 0x00) --方向
+    -- lcd.cmd(0x3a, 0x55)
+    -- lcd.cmd(0x53, 0x20)
+    -- lcd.cmd(0x51, 0xff)
+    lcd.cmd(0x29)
+end