Просмотр исходного кода

add: lcd库支持自定义spi命令集,并修正lcd库中取颜色的代码

Wendal Chen 4 лет назад
Родитель
Сommit
ea262c4c4c
4 измененных файлов с 225 добавлено и 44 удалено
  1. 22 0
      components/lcd/luat_lcd.c
  2. 9 0
      components/lcd/luat_lcd.h
  3. 118 0
      components/lcd/luat_lcd_custom.c
  4. 76 44
      components/lcd/luat_lib_lcd.c

+ 22 - 0
components/lcd/luat_lcd.c

@@ -11,6 +11,28 @@ uint32_t BACK_COLOR = WHITE, FORE_COLOR = BLACK;
 #define LUAT_LCD_CONF_COUNT (2)
 static luat_lcd_conf_t* confs[LUAT_LCD_CONF_COUNT] = {0};
 
+void luat_lcd_execute_cmds(luat_lcd_conf_t* conf, uint32_t* cmds, uint32_t count) {
+    uint32_t cmd = 0;
+    for (size_t i = 0; i < count; i++)
+    {
+        cmd = cmds[i];
+        switch(((cmd >> 16) & 0xFFFF)) {
+            case 0x0001 :
+                luat_timer_mdelay(cmd & 0xFF);
+                break;
+            case 0x0002 :
+                lcd_write_cmd(conf, cmd & 0xFF);
+                break;
+            case 0x0003 :
+                lcd_write_data(conf, cmd & 0xFF);
+                break;
+            default:
+                break;
+        }
+    }
+}
+
+
 int lcd_write_cmd(luat_lcd_conf_t* conf,const uint8_t cmd){
     size_t len;
     luat_gpio_set(conf->pin_dc, Luat_GPIO_LOW);

+ 9 - 0
components/lcd/luat_lcd.h

@@ -71,5 +71,14 @@ int luat_lcd_draw_line(luat_lcd_conf_t* conf,uint16_t x1, uint16_t y1, uint16_t
 int luat_lcd_draw_rectangle(luat_lcd_conf_t* conf,uint16_t x1, uint16_t y1, uint16_t x2, uint16_t y2,uint32_t color);
 int luat_lcd_draw_circle(luat_lcd_conf_t* conf,uint16_t x0, uint16_t y0, uint8_t r,uint32_t color);
 
+void luat_lcd_execute_cmds(luat_lcd_conf_t* conf, uint32_t* cmds, uint32_t count);
+
+typedef struct luat_lcd_custom {
+    uint32_t init_cmd_count;
+    uint32_t sleepcmd;
+    uint32_t wakecmd;
+    uint32_t initcmd[1]; // 实际命令长度与init_cmd_count相同
+}luat_lcd_custom_t;
+
 #endif
 

+ 118 - 0
components/lcd/luat_lcd_custom.c

@@ -0,0 +1,118 @@
+#include "luat_base.h"
+#include "luat_lcd.h"
+#include "luat_gpio.h"
+#include "luat_spi.h"
+#include "luat_malloc.h"
+#include "luat_timer.h"
+
+#define LUAT_LOG_TAG "custom"
+#include "luat_log.h"
+
+#define LCD_W 240
+#define LCD_H 320
+#define LCD_DIRECTION 0
+
+static int custom_sleep(luat_lcd_conf_t* conf) {
+    luat_gpio_set(conf->pin_pwr, Luat_GPIO_LOW);
+    luat_timer_mdelay(5);
+    luat_lcd_custom_t * cst = (luat_lcd_custom_t *)conf->userdata;
+    luat_lcd_execute_cmds(conf, &cst->sleepcmd, 1);
+    return 0;
+}
+
+static int custom_wakeup(luat_lcd_conf_t* conf) {
+    luat_gpio_set(conf->pin_pwr, Luat_GPIO_HIGH);
+    luat_timer_mdelay(5);
+    luat_lcd_custom_t * cst = (luat_lcd_custom_t *)conf->userdata;
+    luat_lcd_execute_cmds(conf, &cst->wakecmd, 1);
+    return 0;
+}
+
+static int custom_close(luat_lcd_conf_t* conf) {
+    luat_gpio_set(conf->pin_pwr, Luat_GPIO_LOW);
+    return 0;
+}
+
+static int custom_init(luat_lcd_conf_t* conf) {
+
+    if (conf->w == 0 || conf->h == 0)
+        conf->h = LCD_H;
+    if (conf->direction == 0)
+        conf->direction = LCD_DIRECTION;
+    luat_gpio_mode(conf->pin_dc, Luat_GPIO_OUTPUT, Luat_GPIO_DEFAULT, Luat_GPIO_HIGH); // DC
+    luat_gpio_mode(conf->pin_pwr, Luat_GPIO_OUTPUT, Luat_GPIO_DEFAULT, Luat_GPIO_LOW); // POWER
+    luat_gpio_mode(conf->pin_rst, Luat_GPIO_OUTPUT, Luat_GPIO_DEFAULT, Luat_GPIO_LOW); // RST
+
+    luat_gpio_set(conf->pin_pwr, Luat_GPIO_LOW);
+    luat_gpio_set(conf->pin_rst, Luat_GPIO_LOW);
+    luat_timer_mdelay(100);
+    luat_gpio_set(conf->pin_rst, Luat_GPIO_HIGH);
+    
+    // 发送初始化命令
+    luat_lcd_custom_t * cst = (luat_lcd_custom_t *)conf->userdata;
+    luat_lcd_execute_cmds(conf, cst->initcmd, cst->init_cmd_count);
+    return 0;
+};
+
+// TODO 这里的color是ARGB, 需要转为lcd所需要的格式
+static int custom_draw(luat_lcd_conf_t* conf, uint16_t x_start, uint16_t y_start, uint16_t x_end, uint16_t y_end, uint32_t* color) {
+    uint16_t i = 0, j = 0;
+    uint32_t size = 0, size_remain = 0;
+    uint8_t *fill_buf = NULL;
+    size = (x_end - x_start+1) * (y_end - y_start+1) * 2;
+    if (size > conf->w*conf->h/10)
+    {
+        /* the number of remaining to be filled */
+        size_remain = size - conf->w*conf->h/10;
+        size = conf->w*conf->h/10;
+    }
+    luat_lcd_set_address(conf,x_start, y_start, x_end, y_end);
+    fill_buf = (uint8_t *)luat_heap_malloc(size);
+    if (fill_buf)
+    {
+        /* fast fill */
+        while (1)
+        {
+            for (i = 0; i < size / 2; i++)
+            {
+                fill_buf[2 * i] = color[i]>>8;
+                //color >> 8;
+                fill_buf[2 * i + 1] = color[i];
+            }
+            luat_gpio_set(conf->pin_dc, Luat_GPIO_HIGH);
+            luat_spi_send(conf->port, fill_buf, size);
+            /* Fill completed */
+            if (size_remain == 0)
+                break;
+            /* calculate the number of fill next time */
+            if (size_remain > conf->w*conf->h/10)
+            {
+                size_remain = size_remain - conf->w*conf->h/10;
+            }
+            else
+            {
+                size = size_remain;
+                size_remain = 0;
+            }
+        }
+        luat_heap_free(fill_buf);
+    }
+    else
+    {
+        for (i = y_start; i <= y_end; i++)
+        {
+            for (j = x_start; j <= x_end; j++)lcd_write_half_word(conf,color[i]);
+        }
+    }
+    return 0;
+}
+
+const luat_lcd_opts_t lcd_opts_custom = {
+    .name = "custom",
+    .init = custom_init,
+    .close = custom_close,
+    .draw = custom_draw,
+    .sleep = custom_sleep,
+    .wakeup = custom_wakeup,
+};
+

+ 76 - 44
components/lcd/luat_lib_lcd.c

@@ -18,17 +18,25 @@ extern const luat_lcd_opts_t lcd_opts_gc9a01;
 extern const luat_lcd_opts_t lcd_opts_gc9106l;
 extern const luat_lcd_opts_t lcd_opts_gc9306;
 extern const luat_lcd_opts_t lcd_opts_ili9341;
+extern const luat_lcd_opts_t lcd_opts_custom;
+
+static luat_lcd_conf_t *default_conf = NULL;
+
+#define COLOR_DEFAULT_32BIT (0xFFFFFFFF)
 
 /*
 初始化lcd
-@api lcd.init(tp, buff, args)
-@string lcd类型, 当前支持st7789
+@api lcd.init(tp, args)
+@string lcd类型, 当前支持st7789/st7735/gc9a01/gc9106l/gc9306/ili9341/custom
 @table 附加参数,与具体设备有关
 */
 static int l_lcd_init(lua_State* L) {
     size_t len = 0;
     const char* tp = luaL_checklstring(L, 1, &len);
-    if (!strcmp("st7735", tp) || !strcmp("st7789", tp) || !strcmp("gc9a01", tp) || !strcmp("gc9106l", tp) || !strcmp("gc9306", tp) || !strcmp("ili9341", tp)) {
+    if (!strcmp("st7735", tp) || !strcmp("st7789", tp) 
+            || !strcmp("gc9a01", tp)  || !strcmp("gc9106l", tp) 
+            || !strcmp("gc9306", tp)  || !strcmp("ili9341", tp)
+            || !strcmp("custom", tp)) {
         luat_lcd_conf_t *conf = luat_heap_malloc(sizeof(luat_lcd_conf_t));
         memset(conf, 0, sizeof(luat_lcd_conf_t)); // 填充0,保证无脏数据
 
@@ -95,44 +103,69 @@ static int l_lcd_init(lua_State* L) {
             conf->opts = &lcd_opts_gc9306;
         else if (!strcmp("ili9341", tp))
             conf->opts = &lcd_opts_ili9341;
+        else if (!strcmp("custom", tp)) {
+            conf->opts = &lcd_opts_custom;
+            luat_lcd_custom_t *cst = luat_heap_malloc(sizeof(luat_lcd_custom_t));
+            
+            // 获取initcmd/sleepcmd/wakecmd
+            lua_pushstring(L, "sleepcmd");
+            lua_gettable(L, 2);
+            cst->sleepcmd = luaL_checkinteger(L, -1);
+            lua_pop(L, 1);
+            
+            lua_pushstring(L, "wakecmd");
+            lua_gettable(L, 2);
+            cst->wakecmd = luaL_checkinteger(L, -1);
+            lua_pop(L, 1);
+            
+            lua_pushstring(L, "initcmd");
+            lua_gettable(L, 2);
+            cst->init_cmd_count = lua_rawlen(L, -1);
+            luat_heap_realloc(cst, sizeof(luat_lcd_custom_t) + cst->init_cmd_count * 4);
+            for (size_t i = 1; i <= cst->init_cmd_count; i++)
+            {
+                lua_geti(L, -1, i);
+                cst->initcmd[i-1] = luaL_checkinteger(L, -1);
+                lua_pop(L, 1);
+            }
+            lua_pop(L, 1);
+        }
         int ret = luat_lcd_init(conf);
         lua_pushboolean(L, ret == 0 ? 1 : 0);
-        return 1;
+        if (ret == 0)
+            default_conf = conf;
+        lua_pushlightuserdata(L, conf);
+        return 2;
     }
     return 0;
 }
 
 static int l_lcd_close(lua_State* L) {
-    luat_lcd_conf_t* conf = luat_lcd_get_default();
-    int ret = luat_lcd_close(conf);
+    int ret = luat_lcd_close(default_conf);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 0;
 }
 
 static int l_lcd_display_on(lua_State* L) {
-    luat_lcd_conf_t* conf = luat_lcd_get_default();
-    int ret = luat_lcd_display_on(conf);
+    int ret = luat_lcd_display_on(default_conf);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 0;
 }
 
 static int l_lcd_display_off(lua_State* L) {
-    luat_lcd_conf_t* conf = luat_lcd_get_default();
-    int ret = luat_lcd_display_off(conf);
+    int ret = luat_lcd_display_off(default_conf);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 0;
 }
 
 static int l_lcd_sleep(lua_State* L) {
-    luat_lcd_conf_t* conf = luat_lcd_get_default();
-    int ret = luat_lcd_sleep(conf);
+    int ret = luat_lcd_sleep(default_conf);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 0;
 }
 
 static int l_lcd_wakeup(lua_State* L) {
-    luat_lcd_conf_t* conf = luat_lcd_get_default();
-    int ret = luat_lcd_wakeup(conf);
+    int ret = luat_lcd_wakeup(default_conf);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 0;
 }
@@ -141,99 +174,97 @@ static int l_lcd_set_color(lua_State* L) {
     uint32_t back,fore;
     back = luaL_checkinteger(L, 1);
     fore = luaL_checkinteger(L, 2);
-    int ret = luat_lcd_set_color(back,fore);
+    int ret = luat_lcd_set_color(back, fore);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 0;
 }
 
 static int l_lcd_draw(lua_State* L) {
-    size_t len = 0;
     uint16_t x1, y1, x2, y2;
-    const char* color = NULL;
-    luat_lcd_conf_t* conf = luat_lcd_get_default();
+    uint32_t color = COLOR_DEFAULT_32BIT;
     x1 = luaL_checkinteger(L, 1);
     y1 = luaL_checkinteger(L, 2);
     x2 = luaL_checkinteger(L, 3);
     y2 = luaL_checkinteger(L, 4);
     if (lua_gettop(L) > 4)
-        color = luaL_checklstring(L, 5, &len);
-    int ret = luat_lcd_draw(conf, x1, y1, x2, y2,color);
+        color = luaL_checkinteger(L, 5);
+    int ret = luat_lcd_draw(default_conf, x1, y1, x2, y2, color);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 0;
 }
 
 static int l_lcd_clear(lua_State* L) {
     size_t len = 0;
-    const char* color = NULL;
-    luat_lcd_conf_t* conf = luat_lcd_get_default();
+    uint32_t color = COLOR_DEFAULT_32BIT;
     if (lua_gettop(L) > 0)
-        color = luaL_checklstring(L, 1, &len);
-    int ret = luat_lcd_clear(conf, color);
+        color = luaL_checkinteger(L, 1);
+    int ret = luat_lcd_clear(default_conf, color);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 0;
 }
 
 static int l_lcd_draw_point(lua_State* L) {
-    size_t len = 0;
     uint16_t x, y;
-    const char* color = NULL;
-    luat_lcd_conf_t* conf = luat_lcd_get_default();
+    uint32_t color = COLOR_DEFAULT_32BIT;
     x = luaL_checkinteger(L, 1);
     y = luaL_checkinteger(L, 2);
     if (lua_gettop(L) > 2)
-        color = luaL_checklstring(L, 3, &len);
-    int ret = luat_lcd_draw_point(conf, x, y, color);
+        color = luaL_checkinteger(L, 3);
+    int ret = luat_lcd_draw_point(default_conf, x, y, color);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 0;
 }
 
 static int l_lcd_draw_line(lua_State* L) {
-    size_t len = 0;
     uint16_t x1, y1, x2, y2;
-    const char* color = NULL;
-    luat_lcd_conf_t* conf = luat_lcd_get_default();
+    uint32_t color = COLOR_DEFAULT_32BIT;
     x1 = luaL_checkinteger(L, 1);
     y1 = luaL_checkinteger(L, 2);
     x2 = luaL_checkinteger(L, 3);
     y2 = luaL_checkinteger(L, 4);
     if (lua_gettop(L) > 4)
-        color = luaL_checklstring(L, 5, &len);
-    int ret = luat_lcd_draw_line(conf, x1,  y1,  x2,  y2, color);
+        color = luaL_checkinteger(L, 5);
+    int ret = luat_lcd_draw_line(default_conf, x1,  y1,  x2,  y2, color);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 0;
 }
 
 static int l_lcd_draw_rectangle(lua_State* L) {
-    size_t len = 0;
     uint16_t x1, y1, x2, y2;
-    const char* color = NULL;
-    luat_lcd_conf_t* conf = luat_lcd_get_default();
+    uint32_t color = COLOR_DEFAULT_32BIT;
     x1 = luaL_checkinteger(L, 1);
     y1 = luaL_checkinteger(L, 2);
     x2 = luaL_checkinteger(L, 3);
     y2 = luaL_checkinteger(L, 4);
     if (lua_gettop(L) > 4)
-        color = luaL_checklstring(L, 5, &len);
-    int ret = luat_lcd_draw_rectangle(conf, x1,  y1,  x2,  y2, color);
+        color = luaL_checkinteger(L, 5);
+    int ret = luat_lcd_draw_rectangle(default_conf, x1,  y1,  x2,  y2, color);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 0;
 }
 
 static int l_lcd_draw_circle(lua_State* L) {
-    size_t len = 0;
     uint16_t x0, y0, r;
-    const char* color = NULL;
-    luat_lcd_conf_t* conf = luat_lcd_get_default();
+    uint32_t color = COLOR_DEFAULT_32BIT;
     x0 = luaL_checkinteger(L, 1);
     y0 = luaL_checkinteger(L, 2);
     r = luaL_checkinteger(L, 3);
     if (lua_gettop(L) > 3)
-        color = luaL_checklstring(L, 4, &len);
-    int ret = luat_lcd_draw_circle(conf, x0,  y0,  r, color);
+        color = luaL_checkinteger(L, 4);
+    int ret = luat_lcd_draw_circle(default_conf, x0,  y0,  r, color);
     lua_pushboolean(L, ret == 0 ? 1 : 0);
     return 0;
 }
 
+static int l_lcd_set_default(lua_State *L) {
+    if (lua_gettop(L) == 1) {
+        default_conf = lua_touserdata(L, 1);
+        lua_pushboolean(L, 1);
+        return 1;
+    }
+    return 0;
+}
+
 #include "rotable.h"
 static const rotable_Reg reg_lcd[] =
 {
@@ -250,6 +281,7 @@ static const rotable_Reg reg_lcd[] =
     { "drawLine",      l_lcd_draw_line,       0},
     { "drawRectangle",      l_lcd_draw_rectangle,       0},
     { "drawCircle",      l_lcd_draw_circle,       0},
+    { "setDefault", l_lcd_set_default, 0},
 	{ NULL,        NULL,   0}
 };