fix: 对不支持weak的bsp, luat_http_client_onevent报重复定义了
[LuatOS.git] / components / lcd / luat_lib_lcd.c
blob444b7d07d5ccd136179dae9f35278a33b6595355
2 /*
3 @module lcd
4 @summary lcd驱动模块
5 @version 1.0
6 @date 2021.06.16
7 @demo lcd
8 @tag LUAT_USE_LCD
9 */
10 #include "luat_base.h"
11 #include "luat_lcd.h"
12 #include "luat_mem.h"
13 #include "luat_zbuff.h"
14 #include "luat_fs.h"
15 #include "luat_gpio.h"
17 #define LUAT_LOG_TAG "lcd"
18 #include "luat_log.h"
20 #include "u8g2.h"
21 #include "u8g2_luat_fonts.h"
22 #include "luat_u8g2.h"
24 #include "qrcodegen.h"
26 int8_t u8g2_font_decode_get_signed_bits(u8g2_font_decode_t *f, uint8_t cnt);
27 uint8_t u8g2_font_decode_get_unsigned_bits(u8g2_font_decode_t *f, uint8_t cnt);
29 extern luat_color_t BACK_COLOR , FORE_COLOR ;
31 extern const luat_lcd_opts_t lcd_opts_custom;
33 typedef struct lcd_reg {
34 const char *name;
35 const luat_lcd_opts_t *lcd_opts;
36 }lcd_reg_t;
38 static const lcd_reg_t lcd_regs[] = {
39 {"custom", &lcd_opts_custom}, //0 固定为第零个
40 {"st7735", &lcd_opts_st7735},
41 {"st7735v", &lcd_opts_st7735v},
42 {"st7735s", &lcd_opts_st7735s},
43 {"st7789", &lcd_opts_st7789},
44 {"st7796", &lcd_opts_st7796},
45 {"gc9a01", &lcd_opts_gc9a01},
46 {"gc9106l", &lcd_opts_gc9106l},
47 {"gc9306x", &lcd_opts_gc9306x},
48 {"gc9306", &lcd_opts_gc9306x}, //gc9306是gc9306x的别名
49 {"ili9341", &lcd_opts_ili9341},
50 {"ili9486", &lcd_opts_ili9486},
51 {"nv3037", &lcd_opts_nv3037},
52 {"", NULL} // 最后一个必须是空字符串
56 static luat_lcd_conf_t *default_conf = NULL;
57 // static int dft_conf_lua_ref = 0;
59 // 所有绘图相关的函数都应该调用本函数
60 static void lcd_auto_flush(luat_lcd_conf_t *conf) {
61 #ifndef LUAT_USE_LCD_SDL2
62 if (conf == NULL || conf->buff == NULL || conf->auto_flush == 0)
63 return;
64 #endif
65 luat_lcd_flush(conf);
68 luat_color_t lcd_str_fg_color,lcd_str_bg_color;
69 luat_lcd_conf_t *l_lcd_get_default_conf(void) {return default_conf;}
70 LUAT_WEAK void luat_lcd_IF_init(luat_lcd_conf_t* conf){}
71 LUAT_WEAK int luat_lcd_init_in_service(luat_lcd_conf_t* conf){return -1;}
73 lcd显示屏初始化
74 @api lcd.init(tp, args, spi_dev, init_in_service)
75 @string lcd类型,当前支持:<br>st7796<br>st7789<br>st7735<br>st7735v<br>st7735s<br>gc9a01<br>gc9106l<br>gc9306x<br>ili9486<br>custom
76 @table 附加参数,与具体设备有关:<br>pin_pwr(背光)为可选项,可不设置<br>port:spi端口,例如0,1,2...如果为device方式则为"device"<br>pin_dc:lcd数据/命令选择引脚<br>pin_rst:lcd复位引脚<br>pin_pwr:lcd背光引脚 可选项,可不设置<br>direction:lcd屏幕方向 0:0° 1:180° 2:270° 3:90°<br>w:lcd 水平分辨率<br>h:lcd 竖直分辨率<br>xoffset:x偏移(不同屏幕ic 不同屏幕方向会有差异)<br>yoffset:y偏移(不同屏幕ic 不同屏幕方向会有差异)<br>direction0:0°方向命令,(不同屏幕ic会有差异)<br>direction90:90°方向命令,(不同屏幕ic会有差异)<br>direction180:180°方向命令,(不同屏幕ic会有差异)<br>direction270:270°方向命令,(不同屏幕ic会有差异) <br>sleepcmd:睡眠命令,默认0X10<br>wakecmd:唤醒命令,默认0X11 <br>interface_mode lcd模式,默认lcd.WIRE_4_BIT_8_INTERFACE_I
77 @userdata spi设备,当port = "device"时有效
78 @boolean 允许初始化在lcd service里运行,默认是false
79 @usage
80 -- 初始化spi0的st7735s 注意:lcd初始化之前需要先初始化spi
81 spi_lcd = spi.deviceSetup(0,20,0,0,8,2000000,spi.MSB,1,1)
82 log.info("lcd.init",
83 lcd.init("st7735s",{port = "device",pin_dc = 17, pin_pwr = 7,pin_rst = 19,direction = 2,w = 160,h = 80,xoffset = 1,yoffset = 26},spi_lcd))
85 static int l_lcd_init(lua_State* L) {
86 size_t len = 0;
87 luat_lcd_conf_t *conf = luat_heap_malloc(sizeof(luat_lcd_conf_t));
88 if (conf == NULL) {
89 LLOGE("out of system memory!!!");
90 return 0;
92 if (default_conf != NULL) {
93 LLOGD("lcd was inited, skip");
94 lua_pushboolean(L, 1);
95 return 1;
97 #if defined LUAT_USE_LCD_SERVICE
98 uint8_t init_in_service = 0;
99 int ret;
100 if (lua_isboolean(L, 4)) {
101 init_in_service = lua_toboolean(L, 4);
103 #endif
104 memset(conf, 0, sizeof(luat_lcd_conf_t)); // 填充0,保证无脏数据
105 conf->lcd_cs_pin = LUAT_GPIO_NONE;
106 conf->pin_dc = LUAT_GPIO_NONE;
107 conf->pin_pwr = LUAT_GPIO_NONE;
108 conf->interface_mode = LUAT_LCD_IM_4_WIRE_8_BIT_INTERFACE_I;
109 if (lua_type(L, 3) == LUA_TUSERDATA){
110 // 如果是SPI Device模式, 就可能出现变量为local, 从而在某个时间点被GC掉的可能性
111 conf->lcd_spi_device = (luat_spi_device_t*)lua_touserdata(L, 3);
112 lua_pushvalue(L, 3);
113 // 所以, 直接引用之外, 再加上强制引用, 避免被GC
114 // 鉴于LCD不太可能重复初始化, 引用也没什么问题
115 conf->lcd_spi_ref = luaL_ref(L, LUA_REGISTRYINDEX);
116 conf->port = LUAT_LCD_SPI_DEVICE;
118 const char* tp = luaL_checklstring(L, 1, &len);
119 int16_t s_index = -1;//第几个屏幕,-1表示没匹配到
120 for(int i = 0; i < 100; i++){
121 if (strlen(lcd_regs[i].name) == 0)
122 break;
123 if(strcmp(lcd_regs[i].name,tp) == 0){
124 s_index = i;
125 break;
128 if (s_index != -1) {
129 LLOGD("ic support: %s",tp);
130 if (lua_gettop(L) > 1) {
131 conf->opts = (struct luat_lcd_opts *)lcd_regs[s_index].lcd_opts;
132 lua_settop(L, 2); // 丢弃多余的参数
134 lua_pushstring(L, "port");
135 int port = lua_gettable(L, 2);
136 if (conf->port == LUAT_LCD_SPI_DEVICE && port ==LUA_TNUMBER) {
137 LLOGE("port is not device but find luat_spi_device_t");
138 goto end;
139 }else if (conf->port != LUAT_LCD_SPI_DEVICE && LUA_TSTRING == port){
140 LLOGE("port is device but not find luat_spi_device_t");
141 goto end;
142 }else if (LUA_TNUMBER == port) {
143 conf->port = luaL_checkinteger(L, -1);
144 }else if (LUA_TSTRING == port){
145 conf->port = LUAT_LCD_SPI_DEVICE;
147 lua_pop(L, 1);
149 lua_pushstring(L, "pin_dc");
150 if (LUA_TNUMBER == lua_gettable(L, 2)) {
151 conf->pin_dc = luaL_checkinteger(L, -1);
153 lua_pop(L, 1);
155 lua_pushstring(L, "pin_pwr");
156 if (LUA_TNUMBER == lua_gettable(L, 2)) {
157 conf->pin_pwr = luaL_checkinteger(L, -1);
159 lua_pop(L, 1);
161 lua_pushstring(L, "pin_rst");
162 if (LUA_TNUMBER == lua_gettable(L, 2)) {
163 conf->pin_rst = luaL_checkinteger(L, -1);
165 lua_pop(L, 1);
167 lua_pushstring(L, "direction");
168 if (LUA_TNUMBER == lua_gettable(L, 2)) {
169 conf->direction = luaL_checkinteger(L, -1);
171 lua_pop(L, 1);
172 lua_pushstring(L, "direction0");
173 if (LUA_TNUMBER == lua_gettable(L, 2)) {
174 conf->opts->direction0 = luaL_checkinteger(L, -1);
176 lua_pop(L, 1);
177 lua_pushstring(L, "direction90");
178 if (LUA_TNUMBER == lua_gettable(L, 2)) {
179 conf->opts->direction90 = luaL_checkinteger(L, -1);
181 lua_pop(L, 1);
182 lua_pushstring(L, "direction180");
183 if (LUA_TNUMBER == lua_gettable(L, 2)) {
184 conf->opts->direction180 = luaL_checkinteger(L, -1);
186 lua_pop(L, 1);
187 lua_pushstring(L, "direction270");
188 if (LUA_TNUMBER == lua_gettable(L, 2)) {
189 conf->opts->direction270 = luaL_checkinteger(L, -1);
191 lua_pop(L, 1);
193 lua_pushstring(L, "w");
194 if (LUA_TNUMBER == lua_gettable(L, 2)) {
195 conf->w = luaL_checkinteger(L, -1);
197 lua_pop(L, 1);
198 lua_pushstring(L, "h");
199 if (LUA_TNUMBER == lua_gettable(L, 2)) {
200 conf->h = luaL_checkinteger(L, -1);
202 lua_pop(L, 1);
203 conf->buffer_size = (conf->w * conf->h) * 2;
205 lua_pushstring(L, "xoffset");
206 if (LUA_TNUMBER == lua_gettable(L, 2)) {
207 conf->xoffset = luaL_checkinteger(L, -1);
209 lua_pop(L, 1);
211 lua_pushstring(L, "yoffset");
212 if (LUA_TNUMBER == lua_gettable(L, 2)) {
213 conf->yoffset = luaL_checkinteger(L, -1);
215 lua_pop(L, 1);
217 lua_pushstring(L, "sleepcmd");
218 if (LUA_TNUMBER == lua_gettable(L, 2)) {
219 conf->opts->sleep_cmd = luaL_checkinteger(L, -1);
221 lua_pop(L, 1);
223 lua_pushstring(L, "wakecmd");
224 if (LUA_TNUMBER == lua_gettable(L, 2)) {
225 conf->opts->wakeup_cmd = luaL_checkinteger(L, -1);
227 lua_pop(L, 1);
229 lua_pushstring(L, "interface_mode");
230 if (LUA_TNUMBER == lua_gettable(L, 2)) {
231 conf->interface_mode = luaL_checkinteger(L, -1);
233 lua_pop(L, 1);
236 if (s_index == 0){
237 unsigned int cmd = 0;
238 lua_pushstring(L, "initcmd");
239 lua_gettable(L, 2);
240 if (lua_istable(L, -1)) {
241 conf->opts->init_cmds_len = lua_rawlen(L, -1);
242 conf->opts->init_cmds = luat_heap_malloc( conf->opts->init_cmds_len * sizeof(uint16_t));
243 for (size_t i = 1; i <= conf->opts->init_cmds_len; i++){
244 lua_geti(L, -1, i);
245 cmd = luaL_checkinteger(L, -1);
246 conf->opts->init_cmds[i-1] = ((cmd >> 8) & 0xFF00) | (cmd & 0xFF);
247 lua_pop(L, 1);
249 }else if(lua_isstring(L, -1)){
250 size_t len;
251 const char *fail_name = luaL_checklstring(L, -1, &len);
252 FILE* fd = (FILE *)luat_fs_fopen(fail_name, "rb");
253 conf->opts->init_cmds_len = 0;
254 if (fd){
255 #define INITCMD_BUFF_SIZE 128
256 char init_cmd_buff[INITCMD_BUFF_SIZE] ;
257 conf->opts->init_cmds = luat_heap_malloc(sizeof(uint16_t));
258 while (1) {
259 memset(init_cmd_buff, 0, INITCMD_BUFF_SIZE);
260 int readline_len = luat_fs_readline(init_cmd_buff, INITCMD_BUFF_SIZE-1, fd);
261 if (readline_len < 1)
262 break;
263 if (memcmp(init_cmd_buff, "#", 1)==0){
264 continue;
266 char *token = strtok(init_cmd_buff, ",");
267 if (sscanf(token,"%x",&cmd) < 1){
268 continue;
270 conf->opts->init_cmds_len = conf->opts->init_cmds_len + 1;
271 conf->opts->init_cmds = luat_heap_realloc(conf->opts->init_cmds,conf->opts->init_cmds_len * sizeof(uint16_t));
272 conf->opts->init_cmds[conf->opts->init_cmds_len-1]=((cmd >> 8) & 0xFF00) | (cmd & 0xFF);;
273 while( token != NULL ) {
274 token = strtok(NULL, ",");
275 if (sscanf(token,"%x",&cmd) < 1){
276 break;
278 conf->opts->init_cmds_len = conf->opts->init_cmds_len + 1;
279 conf->opts->init_cmds = luat_heap_realloc(conf->opts->init_cmds,conf->opts->init_cmds_len * sizeof(uint16_t));
280 conf->opts->init_cmds[conf->opts->init_cmds_len-1]=((cmd >> 8) & 0xFF00) | (cmd & 0xFF);;
283 conf->opts->init_cmds[conf->opts->init_cmds_len]= 0;
284 luat_fs_fclose(fd);
285 }else{
286 LLOGE("init_cmd fail open error");
289 lua_pop(L, 1);
291 // 默认自动flush,即使没有buff
292 conf->auto_flush = 1;
294 #ifdef LUAT_USE_LCD_SDL2
295 extern const luat_lcd_opts_t lcd_opts_sdl2;
296 conf->opts = &lcd_opts_sdl2;
297 #endif
298 if (conf->port == LUAT_LCD_HW_ID_0) luat_lcd_IF_init(conf);
299 #if defined LUAT_USE_LCD_SERVICE
300 if (init_in_service) {
301 ret = luat_lcd_init_in_service(conf);
302 } else {
303 ret = luat_lcd_init(conf);
306 #else
307 int ret = luat_lcd_init(conf);
308 #endif
309 if (ret != 0) {
310 LLOGE("lcd init fail %d", ret);
311 luat_heap_free(conf);
312 lua_pushboolean(L, 0);
313 return 0;
315 // 初始化OK, 配置额外的参数
316 default_conf = conf;
317 u8g2_SetFont(&(conf->luat_lcd_u8g2), u8g2_font_opposansm12);
318 u8g2_SetFontMode(&(conf->luat_lcd_u8g2), 0);
319 u8g2_SetFontDirection(&(conf->luat_lcd_u8g2), 0);
320 lua_pushboolean(L, 1);
321 return 1;
323 LLOGE("ic not support: %s",tp);
324 end:
325 lua_pushboolean(L, 0);
326 luat_heap_free(conf);
327 return 1;
331 关闭lcd显示屏
332 @api lcd.close()
333 @usage
334 -- 关闭lcd
335 lcd.close()
337 static int l_lcd_close(lua_State* L) {
338 int ret = luat_lcd_close(default_conf);
339 lua_pushboolean(L, ret == 0 ? 1 : 0);
340 return 1;
344 开启lcd显示屏背光
345 @api lcd.on()
346 @usage
347 -- 开启lcd显示屏背光
348 lcd.on()
350 static int l_lcd_display_on(lua_State* L) {
351 int ret = luat_lcd_display_on(default_conf);
352 lua_pushboolean(L, ret == 0 ? 1 : 0);
353 return 1;
357 关闭lcd显示屏背光
358 @api lcd.off()
359 @usage
360 -- 关闭lcd显示屏背光
361 lcd.off()
363 static int l_lcd_display_off(lua_State* L) {
364 int ret = luat_lcd_display_off(default_conf);
365 lua_pushboolean(L, ret == 0 ? 1 : 0);
366 return 1;
370 lcd睡眠
371 @api lcd.sleep()
372 @usage
373 -- lcd睡眠
374 lcd.sleep()
376 static int l_lcd_sleep(lua_State* L) {
377 int ret = luat_lcd_sleep(default_conf);
378 lua_pushboolean(L, ret == 0 ? 1 : 0);
379 return 1;
383 lcd唤醒
384 @api lcd.wakeup()
385 @usage
386 -- lcd唤醒
387 lcd.wakeup()
389 static int l_lcd_wakeup(lua_State* L) {
390 int ret = luat_lcd_wakeup(default_conf);
391 lua_pushboolean(L, ret == 0 ? 1 : 0);
392 return 1;
396 lcd反显
397 @api lcd.invon()
398 @usage
399 -- lcd反显
400 lcd.invon()
402 static int l_lcd_inv_on(lua_State* L) {
403 int ret = luat_lcd_inv_on(default_conf);
404 lua_pushboolean(L, ret == 0 ? 1 : 0);
405 return 1;
409 lcd反显关闭
410 @api lcd.invoff()
411 @usage
412 -- lcd反显关闭
413 lcd.invoff()
415 static int l_lcd_inv_off(lua_State* L) {
416 int ret = luat_lcd_inv_off(default_conf);
417 lua_pushboolean(L, ret == 0 ? 1 : 0);
418 return 1;
422 lcd命令
423 @api lcd.cmd(cmd)
424 @int cmd
425 @usage
426 -- lcd命令
427 lcd.cmd(0x21)
429 static int l_lcd_write_cmd(lua_State* L) {
430 int ret = lcd_write_cmd_data(default_conf,(uint8_t)luaL_checkinteger(L, 1), NULL, 0);
431 lua_pushboolean(L, ret == 0 ? 1 : 0);
432 return 1;
436 lcd数据
437 @api lcd.data(data)
438 @int data
439 @usage
440 -- lcd数据
441 lcd.data(0x21)
443 static int l_lcd_write_data(lua_State* L) {
444 int ret = lcd_write_data(default_conf,(const uint8_t)luaL_checkinteger(L, 1));
445 lua_pushboolean(L, ret == 0 ? 1 : 0);
446 return 1;
450 lcd颜色设置
451 @api lcd.setColor(back,fore)
452 @int 背景色
453 @int 前景色
454 @usage
455 -- lcd颜色设置
456 lcd.setColor(0xFFFF,0x0000)
458 static int l_lcd_set_color(lua_State* L) {
459 luat_color_t back,fore;
460 back = (luat_color_t)luaL_checkinteger(L, 1);
461 fore = (luat_color_t)luaL_checkinteger(L, 2);
462 int ret = luat_lcd_set_color(back, fore);
463 lua_pushboolean(L, ret == 0 ? 1 : 0);
464 return 1;
467 static int l_lcd_set_direction(lua_State* L) {
468 int ret = luat_lcd_set_direction(default_conf, (uint8_t)luaL_checkinteger(L, 1));
469 lua_pushboolean(L, ret == 0 ? 1 : 0);
470 return 1;
474 lcd颜色填充
475 @api lcd.draw(x1, y1, x2, y2,color)
476 @int 左上边缘的X位置.
477 @int 左上边缘的Y位置.
478 @int 右下边缘的X位置.
479 @int 右下边缘的Y位置.
480 @string 字符串或zbuff对象
481 @usage
482 -- lcd颜色填充
483 local buff = zbuff.create({201,1,16},0x001F)
484 lcd.draw(20,30,220,30,buff)
486 static int l_lcd_draw(lua_State* L) {
487 int16_t x1, y1, x2, y2;
488 int ret;
489 // luat_color_t *color = NULL;
490 luat_zbuff_t *buff;
491 x1 = luaL_checkinteger(L, 1);
492 y1 = luaL_checkinteger(L, 2);
493 x2 = luaL_checkinteger(L, 3);
494 y2 = luaL_checkinteger(L, 4);
495 if (lua_isinteger(L, 5)) {
496 // color = (luat_color_t *)luaL_checkstring(L, 5);
497 luat_color_t color = (luat_color_t)luaL_checkinteger(L, 1);
498 ret = luat_lcd_draw(default_conf, x1, y1, x2, y2, &color);
500 else if (lua_isuserdata(L, 5)) {
501 buff = luaL_checkudata(L, 5, LUAT_ZBUFF_TYPE);
502 luat_color_t *color = (luat_color_t *)buff->addr;
503 ret = luat_lcd_draw(default_conf, x1, y1, x2, y2, color);
505 else if(lua_isstring(L, 5)) {
506 luat_color_t *color = (luat_color_t *)luaL_checkstring(L, 5);
507 ret = luat_lcd_draw(default_conf, x1, y1, x2, y2, color);
509 else {
510 return 0;
512 lcd_auto_flush(default_conf);
513 // int ret = luat_lcd_draw(default_conf, x1, y1, x2, y2, color);
514 lua_pushboolean(L, ret == 0 ? 1 : 0);
515 return 1;
519 lcd清屏
520 @api lcd.clear(color)
521 @int 屏幕颜色 可选参数,默认背景色
522 @usage
523 -- lcd清屏
524 lcd.clear()
526 static int l_lcd_clear(lua_State* L) {
527 //size_t len = 0;
528 luat_color_t color = BACK_COLOR;
529 if (lua_gettop(L) > 0)
530 color = (luat_color_t)luaL_checkinteger(L, 1);
531 int ret = luat_lcd_clear(default_conf, color);
532 lcd_auto_flush(default_conf);
533 lua_pushboolean(L, ret == 0 ? 1 : 0);
534 return 1;
538 lcd颜色填充
539 @api lcd.fill(x1, y1, x2, y2,color)
540 @int 左上边缘的X位置.
541 @int 左上边缘的Y位置.
542 @int 右下边缘的X位置,不含
543 @int 右下边缘的Y位置,不含
544 @int 绘画颜色 可选参数,默认背景色
545 @usage
546 -- lcd颜色填充
547 lcd.fill(20,30,220,30,0x0000)
549 static int l_lcd_draw_fill(lua_State* L) {
550 int16_t x1, y1, x2, y2;
551 luat_color_t color = BACK_COLOR;
552 x1 = luaL_checkinteger(L, 1);
553 y1 = luaL_checkinteger(L, 2);
554 x2 = luaL_checkinteger(L, 3);
555 y2 = luaL_checkinteger(L, 4);
556 if (lua_gettop(L) > 4)
557 color = (luat_color_t)luaL_checkinteger(L, 5);
558 int ret = luat_lcd_draw_fill(default_conf, x1, y1, x2, y2, color);
559 lcd_auto_flush(default_conf);
560 lua_pushboolean(L, ret == 0 ? 1 : 0);
561 return 1;
565 画一个点.
566 @api lcd.drawPoint(x0,y0,color)
567 @int 点的X位置.
568 @int 点的Y位置.
569 @int 绘画颜色 可选参数,默认前景色
570 @usage
571 lcd.drawPoint(20,30,0x001F)
573 static int l_lcd_draw_point(lua_State* L) {
574 int16_t x, y;
575 luat_color_t color = FORE_COLOR;
576 x = luaL_checkinteger(L, 1);
577 y = luaL_checkinteger(L, 2);
578 if (lua_gettop(L) > 2)
579 color = (luat_color_t)luaL_checkinteger(L, 3);
580 int ret = luat_lcd_draw_point(default_conf, x, y, color);
581 lcd_auto_flush(default_conf);
582 lua_pushboolean(L, ret == 0 ? 1 : 0);
583 return 1;
587 在两点之间画一条线.
588 @api lcd.drawLine(x0,y0,x1,y1,color)
589 @int 第一个点的X位置.
590 @int 第一个点的Y位置.
591 @int 第二个点的X位置.
592 @int 第二个点的Y位置.
593 @int 绘画颜色 可选参数,默认前景色
594 @usage
595 lcd.drawLine(20,30,220,30,0x001F)
597 static int l_lcd_draw_line(lua_State* L) {
598 int16_t x1, y1, x2, y2;
599 luat_color_t color = FORE_COLOR;
600 x1 = luaL_checkinteger(L, 1);
601 y1 = luaL_checkinteger(L, 2);
602 x2 = luaL_checkinteger(L, 3);
603 y2 = luaL_checkinteger(L, 4);
604 if (lua_gettop(L) > 4)
605 color = (luat_color_t)luaL_checkinteger(L, 5);
606 int ret = luat_lcd_draw_line(default_conf, x1, y1, x2, y2, color);
607 lcd_auto_flush(default_conf);
608 lua_pushboolean(L, ret == 0 ? 1 : 0);
609 return 1;
613 从x / y位置(左上边缘)开始绘制一个框
614 @api lcd.drawRectangle(x0,y0,x1,y1,color)
615 @int 左上边缘的X位置.
616 @int 左上边缘的Y位置.
617 @int 右下边缘的X位置.
618 @int 右下边缘的Y位置.
619 @int 绘画颜色 可选参数,默认前景色
620 @usage
621 lcd.drawRectangle(20,40,220,80,0x001F)
623 static int l_lcd_draw_rectangle(lua_State* L) {
624 int16_t x1, y1, x2, y2;
625 luat_color_t color = FORE_COLOR;
626 x1 = luaL_checkinteger(L, 1);
627 y1 = luaL_checkinteger(L, 2);
628 x2 = luaL_checkinteger(L, 3);
629 y2 = luaL_checkinteger(L, 4);
630 if (lua_gettop(L) > 4)
631 color = (luat_color_t)luaL_checkinteger(L, 5);
632 int ret = luat_lcd_draw_rectangle(default_conf, x1, y1, x2, y2, color);
633 lcd_auto_flush(default_conf);
634 lua_pushboolean(L, ret == 0 ? 1 : 0);
635 return 1;
639 从x / y位置(圆心)开始绘制一个圆
640 @api lcd.drawCircle(x0,y0,r,color)
641 @int 圆心的X位置.
642 @int 圆心的Y位置.
643 @int 半径.
644 @int 绘画颜色 可选参数,默认前景色
645 @usage
646 lcd.drawCircle(120,120,20,0x001F)
648 static int l_lcd_draw_circle(lua_State* L) {
649 int16_t x0, y0, r;
650 luat_color_t color = FORE_COLOR;
651 x0 = luaL_checkinteger(L, 1);
652 y0 = luaL_checkinteger(L, 2);
653 r = luaL_checkinteger(L, 3);
654 if (lua_gettop(L) > 3)
655 color = (luat_color_t)luaL_checkinteger(L, 4);
656 int ret = luat_lcd_draw_circle(default_conf, x0, y0, r, color);
657 lcd_auto_flush(default_conf);
658 lua_pushboolean(L, ret == 0 ? 1 : 0);
659 return 1;
663 缓冲区绘制QRCode
664 @api lcd.drawQrcode(x, y, str, size)
665 @int x坐标
666 @int y坐标
667 @string 二维码的内容
668 @int 显示大小 (注意:二维码生成大小与要显示内容和纠错等级有关,生成版本为1-40(对应 21x21 - 177x177)的不定大小,如果和设置大小不同会自动在指定的区域中间显示二维码,如二维码未显示请查看日志提示)
669 @return nil 无返回值
671 static int l_lcd_drawQrcode(lua_State *L)
673 size_t len;
674 int x = luaL_checkinteger(L, 1);
675 int y = luaL_checkinteger(L, 2);
676 const char* text = luaL_checklstring(L, 3, &len);
677 int size = luaL_checkinteger(L, 4);
678 uint8_t *qrcode = luat_heap_malloc(qrcodegen_BUFFER_LEN_MAX);
679 uint8_t *tempBuffer = luat_heap_malloc(qrcodegen_BUFFER_LEN_MAX);
680 if (qrcode == NULL || tempBuffer == NULL) {
681 if (qrcode)
682 luat_heap_free(qrcode);
683 if (tempBuffer)
684 luat_heap_free(tempBuffer);
685 LLOGE("qrcode out of memory");
686 return 0;
688 bool ok = qrcodegen_encodeText(text, tempBuffer, qrcode, qrcodegen_Ecc_LOW,
689 qrcodegen_VERSION_MIN, qrcodegen_VERSION_MAX, qrcodegen_Mask_AUTO, true);
690 if (ok){
691 int qr_size = qrcodegen_getSize(qrcode);
692 if (size < qr_size){
693 LLOGE("size must be greater than qr_size %d",qr_size);
694 goto end;
696 int scale = size / qr_size ;
697 if (!scale)scale = 1;
698 int margin = (size - qr_size * scale) / 2;
699 luat_lcd_draw_fill(default_conf,x,y,x+size,y+size,BACK_COLOR);
700 x+=margin;
701 y+=margin;
702 for (int j = 0; j < qr_size; j++) {
703 for (int i = 0; i < qr_size; i++) {
704 if (qrcodegen_getModule(qrcode, i, j))
705 luat_lcd_draw_fill(default_conf,x+i*scale,y+j*scale,x+(i+1)*scale,y+(j+1)*scale,FORE_COLOR);
708 }else{
709 LLOGE("qrcodegen_encodeText false");
711 end:
712 if (qrcode)
713 luat_heap_free(qrcode);
714 if (tempBuffer)
715 luat_heap_free(tempBuffer);
716 lcd_auto_flush(default_conf);
717 return 0;
720 static uint8_t utf8_state;
721 static uint16_t encoding;
722 static uint16_t utf8_next(uint8_t b)
724 if ( b == 0 ) /* '\n' terminates the string to support the string list procedures */
725 return 0x0ffff; /* end of string detected, pending UTF8 is discarded */
726 if ( utf8_state == 0 )
728 if ( b >= 0xfc ) /* 6 byte sequence */
730 utf8_state = 5;
731 b &= 1;
733 else if ( b >= 0xf8 )
735 utf8_state = 4;
736 b &= 3;
738 else if ( b >= 0xf0 )
740 utf8_state = 3;
741 b &= 7;
743 else if ( b >= 0xe0 )
745 utf8_state = 2;
746 b &= 15;
748 else if ( b >= 0xc0 )
750 utf8_state = 1;
751 b &= 0x01f;
753 else
755 /* do nothing, just use the value as encoding */
756 return b;
758 encoding = b;
759 return 0x0fffe;
761 else
763 utf8_state--;
764 /* The case b < 0x080 (an illegal UTF8 encoding) is not checked here. */
765 encoding<<=6;
766 b &= 0x03f;
767 encoding |= b;
768 if ( utf8_state != 0 )
769 return 0x0fffe; /* nothing to do yet */
771 return encoding;
774 static void u8g2_draw_hv_line(u8g2_t *u8g2, int16_t x, int16_t y, int16_t len, uint8_t dir, uint16_t color){
775 switch(dir)
777 case 0:
778 luat_lcd_draw_hline(default_conf,x,y,len,color);
779 break;
780 case 1:
781 luat_lcd_draw_vline(default_conf,x,y,len,color);
782 break;
783 case 2:
784 luat_lcd_draw_hline(default_conf,x-len+1,y,len,color);
785 break;
786 case 3:
787 luat_lcd_draw_vline(default_conf,x,y-len+1,len,color);
788 break;
792 static void u8g2_font_decode_len(u8g2_t *u8g2, uint8_t len, uint8_t is_foreground){
793 uint8_t cnt; /* total number of remaining pixels, which have to be drawn */
794 uint8_t rem; /* remaining pixel to the right edge of the glyph */
795 uint8_t current; /* number of pixels, which need to be drawn for the draw procedure */
796 /* current is either equal to cnt or equal to rem */
797 /* local coordinates of the glyph */
798 uint8_t lx,ly;
799 /* target position on the screen */
800 int16_t x, y;
801 u8g2_font_decode_t *decode = &(u8g2->font_decode);
802 cnt = len;
803 /* get the local position */
804 lx = decode->x;
805 ly = decode->y;
806 for(;;){
807 /* calculate the number of pixel to the right edge of the glyph */
808 rem = decode->glyph_width;
809 rem -= lx;
810 /* calculate how many pixel to draw. This is either to the right edge */
811 /* or lesser, if not enough pixel are left */
812 current = rem;
813 if ( cnt < rem )
814 current = cnt;
815 /* now draw the line, but apply the rotation around the glyph target position */
816 //u8g2_font_decode_draw_pixel(u8g2, lx,ly,current, is_foreground);
817 // printf("lx:%d,ly:%d,current:%d, is_foreground:%d \r\n",lx,ly,current, is_foreground);
818 /* get target position */
819 x = decode->target_x;
820 y = decode->target_y;
821 /* apply rotation */
822 x = u8g2_add_vector_x(x, lx, ly, decode->dir);
823 y = u8g2_add_vector_y(y, lx, ly, decode->dir);
824 /* draw foreground and background (if required) */
825 if ( current > 0 ) /* avoid drawing zero length lines, issue #4 */
827 if ( is_foreground )
829 u8g2_draw_hv_line(u8g2, x, y, current, decode->dir, lcd_str_fg_color);
831 // else if ( decode->is_transparent == 0 )
832 // {
833 // u8g2_draw_hv_line(u8g2, x, y, current, decode->dir, lcd_str_bg_color);
834 // }
836 /* check, whether the end of the run length code has been reached */
837 if ( cnt < rem )
838 break;
839 cnt -= rem;
840 lx = 0;
841 ly++;
843 lx += cnt;
844 decode->x = lx;
845 decode->y = ly;
847 static void u8g2_font_setup_decode(u8g2_t *u8g2, const uint8_t *glyph_data)
849 u8g2_font_decode_t *decode = &(u8g2->font_decode);
850 decode->decode_ptr = glyph_data;
851 decode->decode_bit_pos = 0;
853 /* 8 Nov 2015, this is already done in the glyph data search procedure */
855 decode->decode_ptr += 1;
856 decode->decode_ptr += 1;
859 decode->glyph_width = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_char_width);
860 decode->glyph_height = u8g2_font_decode_get_unsigned_bits(decode,u8g2->font_info.bits_per_char_height);
863 static int8_t u8g2_font_decode_glyph(u8g2_t *u8g2, const uint8_t *glyph_data){
864 uint8_t a, b;
865 int8_t x, y;
866 int8_t d;
867 int8_t h;
868 u8g2_font_decode_t *decode = &(u8g2->font_decode);
869 u8g2_font_setup_decode(u8g2, glyph_data);
870 h = u8g2->font_decode.glyph_height;
871 x = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_x);
872 y = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_y);
873 d = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_delta_x);
875 if ( decode->glyph_width > 0 )
877 decode->target_x = u8g2_add_vector_x(decode->target_x, x, -(h+y), decode->dir);
878 decode->target_y = u8g2_add_vector_y(decode->target_y, x, -(h+y), decode->dir);
879 //u8g2_add_vector(&(decode->target_x), &(decode->target_y), x, -(h+y), decode->dir);
880 /* reset local x/y position */
881 decode->x = 0;
882 decode->y = 0;
883 /* decode glyph */
884 for(;;){
885 a = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_0);
886 b = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_1);
888 u8g2_font_decode_len(u8g2, a, 0);
889 u8g2_font_decode_len(u8g2, b, 1);
890 } while( u8g2_font_decode_get_unsigned_bits(decode, 1) != 0 );
891 if ( decode->y >= h )
892 break;
895 return d;
897 const uint8_t *u8g2_font_get_glyph_data(u8g2_t *u8g2, uint16_t encoding);
898 static int16_t u8g2_font_draw_glyph(u8g2_t *u8g2, int16_t x, int16_t y, uint16_t encoding){
899 int16_t dx = 0;
900 u8g2->font_decode.target_x = x;
901 u8g2->font_decode.target_y = y;
902 const uint8_t *glyph_data = u8g2_font_get_glyph_data(u8g2, encoding);
903 if ( glyph_data != NULL ){
904 dx = u8g2_font_decode_glyph(u8g2, glyph_data);
906 return dx;
908 extern void luat_u8g2_set_ascii_indentation(uint8_t value);
910 设置字体
911 @api lcd.setFont(font, indentation)
912 @int font lcd.font_XXX 请查阅常量表
913 @int indentation, 等宽字体ascii右侧缩进0~127个pixel,等宽字体的ascii字符可能在右侧有大片空白,用户可以选择删除部分。留空或者超过127则直接删除右半边, 非等宽字体无效
914 @usage
915 -- 设置为字体,对之后的drawStr有效,调用lcd.drawStr前一定要先设置
917 -- 若提示 "only font pointer is allow" , 则代表当前固件不含对应字体, 可使用云编译服务免费定制
918 -- 云编译文档: https://wiki.luatos.com/develop/compile/Cloud_compilation.html
920 -- lcd库的默认字体均以 lcd.font_ 开头
921 lcd.setFont(lcd.font_opposansm12)
922 lcd.drawStr(40,10,"drawStr")
923 sys.wait(2000)
924 lcd.setFont(lcd.font_opposansm12_chinese) -- 具体取值可参考api文档的常量表
925 lcd.drawStr(40,40,"drawStr测试")
927 static int l_lcd_set_font(lua_State *L) {
928 if (!lua_islightuserdata(L, 1)) {
929 LLOGE("only font pointer is allow");
930 return 0;
932 const uint8_t *ptr = (const uint8_t *)lua_touserdata(L, 1);
933 if (ptr == NULL) {
934 LLOGE("only font pointer is allow");
935 return 0;
937 luat_u8g2_set_ascii_indentation(0xff);
938 u8g2_SetFont(&(default_conf->luat_lcd_u8g2), ptr);
939 if (lua_isinteger(L, 2)) {
940 int indentation = luaL_checkinteger(L, 2);
941 luat_u8g2_set_ascii_indentation(indentation);
943 lua_pushboolean(L, 1);
944 return 1;
948 显示字符串
949 @api lcd.drawStr(x,y,str,fg_color)
950 @int x 横坐标
951 @int y 竖坐标 注意:此(x,y)为左下起始坐标
952 @string str 文件内容
953 @int fg_color str颜色 注意:此参数可选,如不填写则使用之前设置的颜色,绘制只会绘制字体部分,背景需要自己清除
954 @usage
955 -- 显示之前先设置为中文字体,对之后的drawStr有效
956 lcd.setFont(lcd.font_opposansm12)
957 lcd.drawStr(40,10,"drawStr")
958 sys.wait(2000)
959 lcd.setFont(lcd.font_opposansm16_chinese)
960 lcd.drawStr(40,40,"drawStr测试")
962 static int l_lcd_draw_str(lua_State* L) {
963 int x, y;
964 size_t sz;
965 const uint8_t* data;
966 x = luaL_checkinteger(L, 1);
967 y = luaL_checkinteger(L, 2);
968 data = (const uint8_t*)luaL_checklstring(L, 3, &sz);
969 lcd_str_fg_color = (luat_color_t)luaL_optinteger(L, 4,FORE_COLOR);
970 // lcd_str_bg_color = (uint32_t)luaL_optinteger(L, 5,BACK_COLOR);
971 if (sz == 0)
972 return 0;
973 uint16_t e;
974 int16_t delta;
975 utf8_state = 0;
977 for(;;){
978 e = utf8_next((uint8_t)*data);
979 if ( e == 0x0ffff )
980 break;
981 data++;
982 if ( e != 0x0fffe ){
983 delta = u8g2_font_draw_glyph(&(default_conf->luat_lcd_u8g2), x, y, e);
984 if (e < 0x0080) delta = luat_u8g2_need_ascii_cut(delta);
985 switch(default_conf->luat_lcd_u8g2.font_decode.dir){
986 case 0:
987 x += delta;
988 break;
989 case 1:
990 y += delta;
991 break;
992 case 2:
993 x -= delta;
994 break;
995 case 3:
996 y -= delta;
997 break;
1001 lcd_auto_flush(default_conf);
1002 return 0;
1005 #ifdef LUAT_USE_GTFONT
1007 #include "GT5SLCD2E_1A.h"
1008 extern unsigned int gtfont_draw_w(unsigned char *pBits,unsigned int x,unsigned int y,unsigned int size,unsigned int widt,unsigned int high,int(*point)(void*),void* userdata,int mode);
1009 extern void gtfont_draw_gray_hz(unsigned char *data,unsigned short x,unsigned short y,unsigned short w ,unsigned short h,unsigned char grade, unsigned char HB_par,int(*point)(void*,uint16_t, uint16_t, uint32_t),void* userdata,int mode);
1012 使用gtfont显示gb2312字符串
1013 @api lcd.drawGtfontGb2312(str,size,x,y)
1014 @string str 显示字符串
1015 @int size 字体大小 (支持16-192号大小字体)
1016 @int x 横坐标
1017 @int y 竖坐标
1018 @usage
1019 -- 注意, gtfont是额外的字体芯片硬件, 需要外挂在SPI总线才能调用本函数的
1020 lcd.drawGtfontGb2312("啊啊啊",32,0,0)
1023 使用gtfont显示gbk字符串
1024 @api lcd.drawGtfontGbk(str,size,x,y)
1025 @string str 显示字符串
1026 @int size 字体大小 (支持16-192号大小字体)
1027 @int x 横坐标
1028 @int y 竖坐标
1029 @usage
1030 -- 注意, gtfont是额外的字体芯片硬件, 需要外挂在SPI总线才能调用本函数的
1031 lcd.drawGtfontGbk("啊啊啊",32,0,0)
1033 static int l_lcd_draw_gtfont_gbk(lua_State *L) {
1034 unsigned char buf[128];
1035 size_t len;
1036 int i = 0;
1037 uint8_t strhigh,strlow ;
1038 uint16_t str;
1039 const char *fontCode = luaL_checklstring(L, 1,&len);
1040 unsigned char size = luaL_checkinteger(L, 2);
1041 int x = luaL_checkinteger(L, 3);
1042 int y = luaL_checkinteger(L, 4);
1043 lcd_str_fg_color = (luat_color_t)luaL_optinteger(L, 5,FORE_COLOR);
1044 // lcd_str_bg_color = (luat_color_t)luaL_optinteger(L, 6,BACK_COLOR);
1045 while ( i < len){
1046 strhigh = *fontCode;
1047 fontCode++;
1048 strlow = *fontCode;
1049 str = (strhigh<<8)|strlow;
1050 fontCode++;
1051 int font_size = get_font(buf, str<0x80?VEC_HZ_ASCII_STY:VEC_BLACK_STY, str, size, size, size);
1052 if(font_size == 0){
1053 LLOGW("get gtfont error size:%d font_size:%d",size,font_size);
1054 return 0;
1056 gtfont_draw_w(buf , x ,y , font_size,size , size,luat_lcd_draw_point,default_conf,0);
1057 x+=size;
1058 i+=2;
1060 lcd_auto_flush(default_conf);
1061 return 0;
1065 使用gtfont灰度显示gb2312字符串
1066 @api lcd.drawGtfontGb2312Gray(str,size,gray,x,y)
1067 @string str 显示字符串
1068 @int size 字体大小 (支持16-192号大小字体)
1069 @int gray 灰度[1阶/2阶/3阶/4阶]
1070 @int x 横坐标
1071 @int y 竖坐标
1072 @usage
1073 -- 注意, gtfont是额外的字体芯片硬件, 需要外挂在SPI总线才能调用本函数的
1074 lcd.drawGtfontGb2312Gray("啊啊啊",32,4,0,40)
1077 使用gtfont灰度显示gbk字符串
1078 @api lcd.drawGtfontGbkGray(str,size,gray,x,y)
1079 @string str 显示字符串
1080 @int size 字体大小 (支持16-192号大小字体)
1081 @int gray 灰度[1阶/2阶/3阶/4阶]
1082 @int x 横坐标
1083 @int y 竖坐标
1084 @usage
1085 -- 注意, gtfont是额外的字体芯片硬件, 需要外挂在SPI总线才能调用本函数的
1086 lcd.drawGtfontGbkGray("啊啊啊",32,4,0,40)
1088 static int l_lcd_draw_gtfont_gbk_gray(lua_State* L) {
1089 unsigned char buf[2048];
1090 size_t len;
1091 int i = 0;
1092 uint8_t strhigh,strlow ;
1093 uint16_t str;
1094 const char *fontCode = luaL_checklstring(L, 1,&len);
1095 unsigned char size = luaL_checkinteger(L, 2);
1096 unsigned char font_g = luaL_checkinteger(L, 3);
1097 int x = luaL_checkinteger(L, 4);
1098 int y = luaL_checkinteger(L, 5);
1099 lcd_str_fg_color = (luat_color_t)luaL_optinteger(L, 6,FORE_COLOR);
1100 // lcd_str_bg_color = (luat_color_t)luaL_optinteger(L, 7,BACK_COLOR);
1101 while ( i < len){
1102 strhigh = *fontCode;
1103 fontCode++;
1104 strlow = *fontCode;
1105 str = (strhigh<<8)|strlow;
1106 fontCode++;
1107 int font_size = get_font(buf, str<0x80?VEC_HZ_ASCII_STY:VEC_BLACK_STY, str, size*font_g, size*font_g, size*font_g);
1108 if(font_size != size*font_g){
1109 LLOGW("get gtfont error size:%d font_size:%d",size,font_size);
1110 return 0;
1112 Gray_Process(buf,size,size,font_g);
1113 gtfont_draw_gray_hz(buf, x, y, size , size, font_g, 1,luat_lcd_draw_point,default_conf,0);
1114 x+=size;
1115 i+=2;
1117 lcd_auto_flush(default_conf);
1118 return 0;
1121 #ifdef LUAT_USE_GTFONT_UTF8
1122 extern unsigned short unicodetogb2312 ( unsigned short chr);
1125 使用gtfont显示UTF8字符串
1126 @api lcd.drawGtfontUtf8(str,size,x,y)
1127 @string str 显示字符串
1128 @int size 字体大小 (支持16-192号大小字体)
1129 @int x 横坐标
1130 @int y 竖坐标
1131 @usage
1132 lcd.drawGtfontUtf8("啊啊啊",32,0,0)
1134 static int l_lcd_draw_gtfont_utf8(lua_State *L) {
1135 unsigned char buf[128] = {0};
1136 size_t len;
1137 int i = 0;
1138 uint8_t strhigh,strlow ;
1139 uint16_t e,str;
1140 const char *fontCode = luaL_checklstring(L, 1,&len);
1141 unsigned char size = luaL_checkinteger(L, 2);
1142 int x = luaL_checkinteger(L, 3);
1143 int y = luaL_checkinteger(L, 4);
1144 lcd_str_fg_color = (luat_color_t)luaL_optinteger(L, 5,FORE_COLOR);
1145 // lcd_str_bg_color = (luat_color_t)luaL_optinteger(L, 6,BACK_COLOR);
1146 for(;;){
1147 e = utf8_next((uint8_t)*fontCode);
1148 if ( e == 0x0ffff )
1149 break;
1150 fontCode++;
1151 if ( e != 0x0fffe ){
1152 uint16_t str = unicodetogb2312(e);
1153 memset(buf,0,128);
1154 int font_size = get_font(buf, str<0x80?VEC_HZ_ASCII_STY:VEC_BLACK_STY, str, size, size, size);
1155 if(font_size == 0){
1156 LLOGW("get gtfont error size:%d font_size:%d",size,font_size);
1157 return 0;
1159 unsigned int dw = gtfont_draw_w(buf , x ,y , font_size,size , size,luat_lcd_draw_point,default_conf,0);
1160 x+=str<0x80?dw:size;
1163 lcd_auto_flush(default_conf);
1164 return 0;
1168 使用gtfont灰度显示UTF8字符串
1169 @api lcd.drawGtfontUtf8Gray(str,size,gray,x,y)
1170 @string str 显示字符串
1171 @int size 字体大小 (支持16-192号大小字体)
1172 @int gray 灰度[1阶/2阶/3阶/4阶]
1173 @int x 横坐标
1174 @int y 竖坐标
1175 @usage
1176 lcd.drawGtfontUtf8Gray("啊啊啊",32,4,0,40)
1178 static int l_lcd_draw_gtfont_utf8_gray(lua_State* L) {
1179 unsigned char buf[2048] = {0};
1180 size_t len;
1181 int i = 0;
1182 uint8_t strhigh,strlow ;
1183 uint16_t e,str;
1184 const char *fontCode = luaL_checklstring(L, 1,&len);
1185 unsigned char size = luaL_checkinteger(L, 2);
1186 unsigned char font_g = luaL_checkinteger(L, 3);
1187 int x = luaL_checkinteger(L, 4);
1188 int y = luaL_checkinteger(L, 5);
1189 lcd_str_fg_color = (luat_color_t)luaL_optinteger(L, 6,FORE_COLOR);
1190 // lcd_str_bg_color = (luat_color_t)luaL_optinteger(L, 7,BACK_COLOR);
1191 for(;;){
1192 e = utf8_next((uint8_t)*fontCode);
1193 if ( e == 0x0ffff )
1194 break;
1195 fontCode++;
1196 if ( e != 0x0fffe ){
1197 uint16_t str = unicodetogb2312(e);
1198 int font_size = get_font(buf, str<0x80?VEC_HZ_ASCII_STY:VEC_BLACK_STY, str, size*font_g, size*font_g, size*font_g);
1199 if(font_size != size*font_g){
1200 LLOGW("get gtfont error size:%d font_size:%d",size,font_size);
1201 return 0;
1203 Gray_Process(buf,size,size,font_g);
1204 gtfont_draw_gray_hz(buf, x, y, size , size, font_g, 1,luat_lcd_draw_point,default_conf,0);
1205 x+=size;
1208 lcd_auto_flush(default_conf);
1209 return 0;
1212 #endif // LUAT_USE_GTFONT_UTF8
1214 #endif // LUAT_USE_GTFONT
1216 static int l_lcd_set_default(lua_State *L) {
1217 if (lua_gettop(L) == 1) {
1218 default_conf = lua_touserdata(L, 1);
1219 lua_pushboolean(L, 1);
1220 return 1;
1222 return 1;
1225 static int l_lcd_get_default(lua_State *L) {
1226 if (default_conf == NULL)
1227 return 0;
1228 lua_pushlightuserdata(L, default_conf);
1229 return 1;
1233 获取屏幕尺寸
1234 @api lcd.getSize()
1235 @return int 宽, 如果未初始化会返回0
1236 @return int 高, 如果未初始化会返回0
1237 @usage
1238 log.info("lcd", "size", lcd.getSize())
1240 static int l_lcd_get_size(lua_State *L) {
1241 if (lua_gettop(L) == 1) {
1242 luat_lcd_conf_t * conf = lua_touserdata(L, 1);
1243 if (conf) {
1244 lua_pushinteger(L, conf->w);
1245 lua_pushinteger(L, conf->h);
1246 return 2;
1249 if (default_conf == NULL) {
1250 lua_pushinteger(L, 0);
1251 lua_pushinteger(L, 0);
1253 else {
1254 lua_pushinteger(L, default_conf->w);
1255 lua_pushinteger(L, default_conf->h);
1257 return 2;
1261 绘制位图
1262 @api lcd.drawXbm(x, y, w, h, data)
1263 @int X坐标
1264 @int y坐标
1265 @int 位图宽
1266 @int 位图高
1267 @int 位图数据,每一位代表一个像素
1268 @usage
1269 -- 取模使用PCtoLCD2002软件即可 阴码 逐行 逆向
1270 -- 在(0,0)为左上角,绘制 16x16 "今" 的位图
1271 lcd.drawXbm(0, 0, 16,16, string.char(
1272 0x80,0x00,0x80,0x00,0x40,0x01,0x20,0x02,0x10,0x04,0x48,0x08,0x84,0x10,0x83,0x60,
1273 0x00,0x00,0xF8,0x0F,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x01,0x80,0x00
1276 static int l_lcd_drawxbm(lua_State *L){
1277 int x = luaL_checkinteger(L, 1);
1278 int y = luaL_checkinteger(L, 2);
1279 size_t w = luaL_checkinteger(L, 3);
1280 size_t h = luaL_checkinteger(L, 4);
1281 size_t len = 0;
1282 const char* data = luaL_checklstring(L, 5, &len);
1283 uint8_t mask = 1;
1284 if (h < 1) return 0; // 行数必须大于0
1285 if (len*8/h < w) return 0; // 起码要填满一行
1286 int w1 = w/8;
1287 if (w%8)w1++;
1288 if (len != h*w1)return 0;
1289 luat_color_t* color_w = luat_heap_malloc(sizeof(luat_color_t) * w);
1290 for (size_t b = 0; b < h; b++){
1291 size_t a = 0;
1292 while (a < w){
1293 for (size_t c = 0; c < 8; c++){
1294 if (*data&(mask<<c)){
1295 color_w[a]=FORE_COLOR;
1296 }else{
1297 color_w[a]=BACK_COLOR;
1299 a++;
1300 if (a == w)break;
1302 data++;
1304 luat_lcd_draw(default_conf, x, y+b, x+w-1, y+b, color_w);
1306 luat_heap_free(color_w);
1307 lcd_auto_flush(default_conf);
1308 lua_pushboolean(L, 1);
1309 return 1;
1312 #ifdef LUAT_USE_TJPGD
1313 #include "tjpgd.h"
1314 #include "tjpgdcnf.h"
1316 #define N_BPP (3 - JD_FORMAT)
1318 /* Session identifier for input/output functions (name, members and usage are as user defined) */
1319 typedef struct {
1320 FILE *fp; /* Input stream */
1321 int x;
1322 int y;
1323 // int width;
1324 // int height;
1325 uint16_t buff[16*16];
1326 } IODEV;
1328 static unsigned int file_in_func (JDEC* jd, uint8_t* buff, unsigned int nbyte){
1329 IODEV *dev = (IODEV*)jd->device; /* Device identifier for the session (5th argument of jd_prepare function) */
1330 if (buff) {
1331 /* Read bytes from input stream */
1332 return luat_fs_fread(buff, 1, nbyte, dev->fp);
1333 } else {
1334 /* Remove bytes from input stream */
1335 return luat_fs_fseek(dev->fp, nbyte, SEEK_CUR) ? 0 : nbyte;
1339 static int lcd_out_func (JDEC* jd, void* bitmap, JRECT* rect){
1340 IODEV *dev = (IODEV*)jd->device;
1341 uint16_t* tmp = (uint16_t*)bitmap;
1343 // rgb高低位swap
1344 uint16_t count = (rect->right - rect->left + 1) * (rect->bottom - rect->top + 1);
1345 for (size_t i = 0; i < count; i++){
1346 if (default_conf->port == LUAT_LCD_HW_ID_0)
1347 dev->buff[i] = tmp[i];
1348 else
1349 dev->buff[i] = ((tmp[i] >> 8) & 0xFF)+ ((tmp[i] << 8) & 0xFF00);
1352 // LLOGD("jpeg seg %dx%d %dx%d", rect->left, rect->top, rect->right, rect->bottom);
1353 // LLOGD("jpeg seg size %d %d %d", rect->right - rect->left + 1, rect->bottom - rect->top + 1, (rect->right - rect->left + 1) * (rect->bottom - rect->top + 1));
1354 luat_lcd_draw(default_conf, dev->x + rect->left, dev->y + rect->top,
1355 dev->x + rect->right, dev->y + rect->bottom,
1356 dev->buff);
1357 return 1; /* Continue to decompress */
1360 static int lcd_draw_jpeg(const char* path, int xpos, int ypos) {
1361 JRESULT res; /* Result code of TJpgDec API */
1362 JDEC jdec; /* Decompression object */
1363 void *work; /* Pointer to the decompressor work area */
1364 #if JD_FASTDECODE == 2
1365 size_t sz_work = 3500 * 3; /* Size of work area */
1366 #else
1367 size_t sz_work = 3500; /* Size of work area */
1368 #endif
1369 IODEV devid; /* User defined device identifier */
1371 FILE* fd = luat_fs_fopen(path, "r");
1372 if (fd == NULL) {
1373 LLOGW("no such file %s", path);
1374 return -1;
1377 devid.fp = fd;
1378 work = luat_heap_malloc(sz_work);
1379 if (work == NULL) {
1380 LLOGE("out of memory when malloc jpeg decode workbuff");
1381 return -3;
1383 res = jd_prepare(&jdec, file_in_func, work, sz_work, &devid);
1384 if (res != JDR_OK) {
1385 luat_heap_free(work);
1386 luat_fs_fclose(fd);
1387 LLOGW("jd_prepare file %s error %d", path, res);
1388 return -2;
1390 devid.x = xpos;
1391 devid.y = ypos;
1392 // devid.width = jdec.width;
1393 // devid.height = jdec.height;
1394 res = jd_decomp(&jdec, lcd_out_func, 0);
1395 luat_heap_free(work);
1396 luat_fs_fclose(fd);
1397 if (res != JDR_OK) {
1398 LLOGW("jd_decomp file %s error %d", path, res);
1399 return -2;
1401 else {
1402 lcd_auto_flush(default_conf);
1403 return 0;
1408 显示图片,当前只支持jpg,jpeg
1409 @api lcd.showImage(x, y, file)
1410 @int X坐标
1411 @int y坐标
1412 @string 文件路径
1413 @usage
1414 lcd.showImage(0,0,"/luadb/logo.jpg")
1416 static int l_lcd_showimage(lua_State *L){
1417 size_t size = 0;
1418 int ret = 0;
1419 int x = luaL_checkinteger(L, 1);
1420 int y = luaL_checkinteger(L, 2);
1421 const char* input_file = luaL_checklstring(L, 3, &size);
1422 if (memcmp(input_file+size-4, ".jpg", 5) == 0 || memcmp(input_file+size-4, ".JPG", 5) == 0 || memcmp(input_file+size-5, ".jpeg", 6) == 0 || memcmp(input_file+size-5, ".JPEG", 6) == 0){
1423 ret = lcd_draw_jpeg(input_file, x, y);
1424 lua_pushboolean(L, ret == 0 ? 1 : 0);
1425 } else{
1426 LLOGE("input_file not support");
1427 lua_pushboolean(L, 0);
1429 return 1;
1431 #endif
1434 主动刷新数据到界面, 仅设置buff且禁用自动属性后使用
1435 @api lcd.flush()
1436 @return bool 成功返回true, 否则返回nil/false
1437 @usage
1438 -- 本API与 lcd.setupBuff lcd.autoFlush 配合使用
1439 lcd.flush()
1441 static int l_lcd_flush(lua_State* L) {
1442 luat_lcd_conf_t * conf = NULL;
1443 if (lua_gettop(L) == 1) {
1444 conf = lua_touserdata(L, 1);
1446 else {
1447 conf = default_conf;
1449 if (conf == NULL) {
1450 //LLOGW("lcd not init");
1451 return 0;
1453 if (conf->buff == NULL) {
1454 //LLOGW("lcd without buff, not support flush");
1455 return 0;
1457 if (conf->auto_flush) {
1458 //LLOGI("lcd auto flush is enable, no need for flush");
1459 return 0;
1461 luat_lcd_flush(conf);
1462 lua_pushboolean(L, 1);
1463 return 0;
1467 设置显示缓冲区, 所需内存大小为 2×宽×高 字节. 请衡量内存需求与业务所需的刷新频次.
1468 @api lcd.setupBuff(conf, onheap)
1469 @userdata conf指针, 不需要传
1470 @bool true使用heap内存, false使用vm内存, 默认使用vm内存, 不需要主动传
1471 @return bool 是否成功
1472 @usage
1473 -- 初始化lcd的buff缓冲区, 可理解为FrameBuffer区域.
1474 lcd.setupBuff()
1476 static int l_lcd_setup_buff(lua_State* L) {
1477 luat_lcd_conf_t * conf = NULL;
1478 if (lua_gettop(L) == 1) {
1479 conf = lua_touserdata(L, 1);
1481 else {
1482 conf = default_conf;
1484 if (conf == NULL) {
1485 LLOGW("lcd not init");
1486 return 0;
1488 if (conf->buff != NULL) {
1489 LLOGW("lcd buff is ok");
1490 return 0;
1492 if (lua_isboolean(L, 2) && lua_toboolean(L, 2)) {
1493 conf->buff = luat_heap_malloc(sizeof(luat_color_t) * conf->w * conf->h);
1495 else {
1496 conf->buff = lua_newuserdata(L, sizeof(luat_color_t) * conf->w * conf->h);
1497 if (conf->buff) {
1498 conf->buff_ref = luaL_ref(L, LUA_REGISTRYINDEX);
1501 if (conf->buff == NULL) {
1502 LLOGE("lcd buff malloc fail, out of memory?");
1503 return 0;
1505 // 先设置为不需要的区间
1506 conf->flush_y_min = conf->h;
1507 conf->flush_y_max = 0;
1508 // luat_lcd_clear 会将区域扩展到整个屏幕
1509 luat_lcd_clear(default_conf, BACK_COLOR);
1510 lua_pushboolean(L, 1);
1511 return 1;
1515 设置自动刷新, 需配合lcd.setupBuff使用
1516 @api lcd.autoFlush(enable)
1517 @bool 是否自动刷新,默认为true
1518 @usage
1519 -- 设置buff 并禁用自动更新
1520 lcd.setupBuff()
1521 lcd.autoFlush(false)
1522 -- 禁止自动更新后, 需要使用 lcd.flush() 主动刷新数据到屏幕
1524 static int l_lcd_auto_flush(lua_State* L) {
1525 luat_lcd_conf_t * conf = default_conf;
1526 if (conf == NULL) {
1527 LLOGW("lcd not init");
1528 return 0;
1530 conf->auto_flush = lua_toboolean(L, 1);
1531 lua_pushboolean(L, conf->auto_flush);
1532 return 1;
1536 RGB565颜色生成
1537 @api lcd.rgb565(r, g, b, swap)
1538 @int 红色, 0x00 ~ 0xFF
1539 @int 绿色, 0x00 ~ 0xFF
1540 @int 蓝色, 0x00 ~ 0xFF
1541 @bool 是否翻转, true 翻转, false 不翻转. 默认翻转
1542 @return int 颜色值
1543 @usage
1544 -- 本API支持多种模式, 参数数量分别是 1, 2, 3, 4
1545 -- 1. 单参数形式, 24bit RGB值, swap = true, 推荐
1546 local red = lcd.rgb565(0xFF0000)
1547 local green = lcd.rgb565(0x00FF00)
1548 local blue = lcd.rgb565(0x0000FF)
1550 -- 2. 两参数形式, 24bit RGB值, 增加swap的设置
1551 local red = lcd.rgb565(0xFF0000, true)
1552 local green = lcd.rgb565(0x00FF00, true)
1553 local blue = lcd.rgb565(0x0000FF, true)
1555 -- 3. 三参数形式, 红/绿/蓝, 各8bit
1556 local red = lcd.rgb565(0xFF, 0x00, 0x00)
1557 local green = lcd.rgb565(0x00, 0xFF, 0x00)
1558 local blue = lcd.rgb565(0x00, 0x00, 0xFF)
1560 -- 4. 四参数形式, 红/绿/蓝, 各8bit, 增加swap的设置
1561 local red = lcd.rgb565(0xFF, 0x00, 0x00, true)
1562 local green = lcd.rgb565(0x00, 0xFF, 0x00, true)
1563 local blue = lcd.rgb565(0x00, 0x00, 0xFF, true)
1565 static int l_lcd_rgb565(lua_State* L) {
1566 uint8_t r =0,g =0,b = 0;
1567 uint8_t swap = 0;
1568 uint16_t dst = 0;
1569 int top = 0 ;
1570 uint32_t rgb = 0;
1571 top = lua_gettop(L);
1572 if (top == 1 || top == 2) {
1573 rgb = luaL_checkinteger(L, 1);
1574 r = (uint8_t)((rgb >> 16 ) & 0xFF);
1575 g = (uint8_t)((rgb >> 8 ) & 0xFF);
1576 b = (uint8_t)((rgb >> 0 ) & 0xFF);
1577 swap = (lua_isboolean(L, 2) && !lua_toboolean(L, 2)) ? 0U : 1U;
1579 else if (top == 3 || top == 4) {
1580 r = (uint8_t)luaL_checkinteger(L, 1);
1581 g = (uint8_t)luaL_checkinteger(L, 2);
1582 b = (uint8_t)luaL_checkinteger(L, 3);
1583 swap = (lua_isboolean(L, 4) && !lua_toboolean(L, 4)) ? 0U : 1U;
1585 else {
1586 LLOGW("unkown args count %d", top);
1587 dst = 0;
1589 dst = (uint16_t)((r&0xF8)<<8) | (uint16_t)((g&0xFC)<<3) | (uint16_t)(b>>3);
1591 if (swap) {
1592 dst = ((dst >> 8) & 0xFF) + ((dst & 0xFF) << 8);
1594 lua_pushinteger(L, dst);
1595 return 1;
1597 #ifdef LUAT_USE_UFONT
1598 #include "luat_ufont.h"
1599 static const int l_lcd_draw_utf8(lua_State *L) {
1600 size_t sz = 0;
1601 uint32_t letter = 0;
1602 uint32_t str_offset;
1603 int ret = 0;
1604 uint16_t draw_offset = 0;
1606 int draw_x = 0;
1607 int draw_y = 0;
1608 luat_font_char_desc_t desc = {0};
1609 // 左上角坐标x,y
1610 int x = luaL_checkinteger(L, 1);
1611 int y = luaL_checkinteger(L, 2);
1612 // 待绘制的字符串
1613 const char* data = (const char*)luaL_checklstring(L, 3, &sz);
1614 // 字体指针
1615 lv_font_t* lfont = (lv_font_t*)lua_touserdata(L, 4);
1616 if (lfont == NULL) {
1617 LLOGW("draw without font");
1618 return 0;
1620 luat_font_header_t* font = (luat_font_header_t*)lfont->dsc;
1621 // 是否填充背景
1622 bool draw_bg = lua_isboolean(L, 5) ? lua_toboolean(L, 5) : true;
1624 // 没内容, 不需要画了
1625 if (sz == 0) {
1626 // 直接返回原坐标
1627 lua_pushinteger(L, x);
1628 return 1;
1631 // 没字体, 不需要画了
1632 if (font == NULL) {
1633 LLOGD("NULL font, skip draw");
1634 // 直接返回原坐标
1635 lua_pushinteger(L, x);
1636 return 1;
1638 // 超边界了没? 超了就没必要绘制了
1639 if (default_conf->h < y || default_conf->w < x) {
1640 //LLOGD("draw y %d h % font->line_height %d", y, default_conf->h, font->line_height);
1641 // 直接返回原坐标
1642 lua_pushinteger(L, x);
1643 return 1;
1646 luat_color_t* buff = NULL;
1647 if (draw_bg)
1648 buff = luat_heap_malloc(font->line_height * font->line_height * 2);
1649 // if (buff == NULL)
1650 // return 0;
1651 int offset = 0;
1652 uint8_t *data_ptr = data;
1653 uint8_t utf8_state = 0;
1654 uint16_t utf8_tmp = 0;
1655 uint16_t utf8_out = 0;
1656 luat_color_t color = FORE_COLOR;
1657 for (size_t i = 0; i < sz; i++)
1659 utf8_out = luat_utf8_next(data[i], &utf8_state, &utf8_tmp);
1660 if (utf8_out == 0x0ffff)
1661 break; // 结束了
1662 if (utf8_out == 0x0fffe)
1663 continue; // 没读完一个字符,继续下一个循环
1664 letter = (uint32_t)utf8_out;
1666 //LLOGD("draw letter %04X", letter);
1667 int ret = luat_font_get_bitmap(font, &desc, letter);
1668 if (ret != 0) {
1669 LLOGD("not such char in font");
1670 draw_offset += font->line_height / 2; // 找不到字符, 默认跳过半个字
1671 continue;
1673 offset = 0;
1674 // desc.data = tmp;
1675 memset(buff, 0, font->line_height * font->line_height * 2);
1676 draw_x = x + draw_offset;
1677 draw_offset += desc.char_w;
1678 if (draw_x >= 0 && draw_x + desc.char_w <= default_conf->w) {
1679 //if (default_conf->buff == NULL) {
1680 for (size_t j = 0; j < font->line_height; j++)
1682 //LLOGD("draw char pix line %d", i);
1683 for (size_t k = 0; k < desc.char_w; k++)
1685 if ((desc.data[offset / 8] >> (7 - (offset % 8))) & 0x01) {
1686 color = FORE_COLOR;
1687 if (buff)
1688 buff[offset] = FORE_COLOR;
1689 else
1690 luat_lcd_draw_point(default_conf, draw_x + k, y + j, FORE_COLOR);
1691 //LLOGD("draw char pix mark %d", offset);
1693 else {
1694 if (buff)
1695 buff[offset] = BACK_COLOR;
1696 //LLOGD("draw char pix offset %d color %04X", offset, FORE_COLOR);
1698 offset ++;
1701 //LLOGD("luat_lcd_draw %d %d %d %d", draw_x, y, draw_x + desc.char_w, y + font->line_height);
1702 luat_lcd_draw(default_conf, draw_x, y, draw_x + desc.char_w - 1, y + font->line_height - 1, buff);
1704 //else {
1709 if (buff)
1710 luat_heap_free(buff);
1712 lcd_auto_flush(default_conf);
1713 lua_pushinteger(L, draw_x + desc.char_w);
1714 return 1;
1716 #endif
1718 #include "rotable2.h"
1719 static const rotable_Reg_t reg_lcd[] =
1721 { "init", ROREG_FUNC(l_lcd_init)},
1722 { "clear", ROREG_FUNC(l_lcd_clear)},
1723 { "fill", ROREG_FUNC(l_lcd_draw_fill)},
1724 { "drawPoint", ROREG_FUNC(l_lcd_draw_point)},
1725 { "drawLine", ROREG_FUNC(l_lcd_draw_line)},
1726 { "drawRectangle", ROREG_FUNC(l_lcd_draw_rectangle)},
1727 { "drawCircle", ROREG_FUNC(l_lcd_draw_circle)},
1728 { "drawQrcode", ROREG_FUNC(l_lcd_drawQrcode)},
1729 { "drawStr", ROREG_FUNC(l_lcd_draw_str)},
1730 { "flush", ROREG_FUNC(l_lcd_flush)},
1731 { "setupBuff", ROREG_FUNC(l_lcd_setup_buff)},
1732 { "autoFlush", ROREG_FUNC(l_lcd_auto_flush)},
1733 { "setFont", ROREG_FUNC(l_lcd_set_font)},
1734 { "setDefault", ROREG_FUNC(l_lcd_set_default)},
1735 { "getDefault", ROREG_FUNC(l_lcd_get_default)},
1736 { "getSize", ROREG_FUNC(l_lcd_get_size)},
1737 { "drawXbm", ROREG_FUNC(l_lcd_drawxbm)},
1738 { "close", ROREG_FUNC(l_lcd_close)},
1739 { "on", ROREG_FUNC(l_lcd_display_on)},
1740 { "off", ROREG_FUNC(l_lcd_display_off)},
1741 { "sleep", ROREG_FUNC(l_lcd_sleep)},
1742 { "wakeup", ROREG_FUNC(l_lcd_wakeup)},
1743 { "invon", ROREG_FUNC(l_lcd_inv_on)},
1744 { "invoff", ROREG_FUNC(l_lcd_inv_off)},
1745 { "cmd", ROREG_FUNC(l_lcd_write_cmd)},
1746 { "data", ROREG_FUNC(l_lcd_write_data)},
1747 { "setColor", ROREG_FUNC(l_lcd_set_color)},
1748 { "draw", ROREG_FUNC(l_lcd_draw)},
1749 { "rgb565", ROREG_FUNC(l_lcd_rgb565)},
1750 #ifdef LUAT_USE_UFONT
1751 { "drawUTF8", ROREG_FUNC(l_lcd_draw_utf8)},
1752 #endif
1753 #ifdef LUAT_USE_TJPGD
1754 { "showImage", ROREG_FUNC(l_lcd_showimage)},
1755 #endif
1756 #ifdef LUAT_USE_GTFONT
1757 { "drawGtfontGb2312", ROREG_FUNC(l_lcd_draw_gtfont_gbk)},
1758 { "drawGtfontGb2312Gray", ROREG_FUNC(l_lcd_draw_gtfont_gbk_gray)},
1759 { "drawGtfontGbk", ROREG_FUNC(l_lcd_draw_gtfont_gbk)},
1760 { "drawGtfontGbkGray", ROREG_FUNC(l_lcd_draw_gtfont_gbk_gray)},
1761 #ifdef LUAT_USE_GTFONT_UTF8
1762 { "drawGtfontUtf8", ROREG_FUNC(l_lcd_draw_gtfont_utf8)},
1763 { "drawGtfontUtf8Gray", ROREG_FUNC(l_lcd_draw_gtfont_utf8_gray)},
1764 #endif // LUAT_USE_GTFONT_UTF8
1765 #endif // LUAT_USE_GTFONT
1766 // 默认只带英文12号字体
1767 //@const font_opposansm12 font 12号字体
1768 { "font_opposansm12", ROREG_PTR((void*)u8g2_font_opposansm12)},
1769 #ifdef USE_U8G2_OPPOSANSM_ENGLISH
1770 //@const font_unifont_t_symbols font 符号字体
1771 { "font_unifont_t_symbols", ROREG_PTR((void*)u8g2_font_unifont_t_symbols)},
1772 //@const font_open_iconic_weather_6x_t font 天气字体
1773 { "font_open_iconic_weather_6x_t", ROREG_PTR((void*)u8g2_font_open_iconic_weather_6x_t)},
1775 //@const font_opposansm16 font 16号字体
1776 //@const font_opposansm18 font 18号字体
1777 //@const font_opposansm20 font 20号字体
1778 //@const font_opposansm22 font 22号字体
1779 //@const font_opposansm24 font 24号字体
1780 //@const font_opposansm32 font 32号字体
1781 { "font_opposansm16", ROREG_PTR((void*)u8g2_font_opposansm16)},
1782 { "font_opposansm18", ROREG_PTR((void*)u8g2_font_opposansm18)},
1783 { "font_opposansm20", ROREG_PTR((void*)u8g2_font_opposansm20)},
1784 { "font_opposansm22", ROREG_PTR((void*)u8g2_font_opposansm22)},
1785 { "font_opposansm24", ROREG_PTR((void*)u8g2_font_opposansm24)},
1786 { "font_opposansm32", ROREG_PTR((void*)u8g2_font_opposansm32)},
1787 #endif
1788 #ifdef USE_U8G2_OPPOSANSM12_CHINESE
1789 //@const font_opposansm12_chinese font 12号中文字体
1790 { "font_opposansm12_chinese", ROREG_PTR((void*)u8g2_font_opposansm12_chinese)},
1791 #endif
1792 #ifdef USE_U8G2_OPPOSANSM14_CHINESE
1793 //@const font_opposansm14_chinese font 14号中文字体
1794 { "font_opposansm14_chinese", ROREG_PTR((void*)u8g2_font_opposansm14_chinese)},
1795 #endif
1796 #ifdef USE_U8G2_OPPOSANSM16_CHINESE
1797 //@const font_opposansm16_chinese font 16号中文字体
1798 { "font_opposansm16_chinese", ROREG_PTR((void*)u8g2_font_opposansm16_chinese)},
1799 #endif
1800 #ifdef USE_U8G2_OPPOSANSM18_CHINESE
1801 //@const font_opposansm18_chinese font 18号中文字体
1802 { "font_opposansm18_chinese", ROREG_PTR((void*)u8g2_font_opposansm18_chinese)},
1803 #endif
1804 #ifdef USE_U8G2_OPPOSANSM20_CHINESE
1805 //@const font_opposansm20_chinese font 20号中文字体
1806 { "font_opposansm20_chinese", ROREG_PTR((void*)u8g2_font_opposansm20_chinese)},
1807 #endif
1808 #ifdef USE_U8G2_OPPOSANSM22_CHINESE
1809 //@const font_opposansm22_chinese font 22号中文字体
1810 { "font_opposansm22_chinese", ROREG_PTR((void*)u8g2_font_opposansm22_chinese)},
1811 #endif
1812 #ifdef USE_U8G2_OPPOSANSM24_CHINESE
1813 //@const font_opposansm24_chinese font 24号中文字体
1814 { "font_opposansm24_chinese", ROREG_PTR((void*)u8g2_font_opposansm24_chinese)},
1815 #endif
1816 #ifdef USE_U8G2_OPPOSANSM32_CHINESE
1817 //@const font_opposansm32_chinese font 32号中文字体
1818 { "font_opposansm32_chinese", ROREG_PTR((void*)u8g2_font_opposansm32_chinese)},
1819 #endif
1820 #ifdef USE_U8G2_SARASA_ENGLISH
1821 { "font_sarasa_m12_ascii", ROREG_PTR((void*)u8g2_font_sarasa_m12_ascii)},
1822 { "font_sarasa_m14_ascii", ROREG_PTR((void*)u8g2_font_sarasa_m14_ascii)},
1823 { "font_sarasa_m16_ascii", ROREG_PTR((void*)u8g2_font_sarasa_m16_ascii)},
1824 { "font_sarasa_m18_ascii", ROREG_PTR((void*)u8g2_font_sarasa_m18_ascii)},
1825 { "font_sarasa_m20_ascii", ROREG_PTR((void*)u8g2_font_sarasa_m20_ascii)},
1826 { "font_sarasa_m22_ascii", ROREG_PTR((void*)u8g2_font_sarasa_m22_ascii)},
1827 //再大的很少用到先不加了
1828 #endif
1830 // #ifdef USE_U8G2_SARASA_M8_CHINESE
1831 // { "font_sarasa_m8_chinese", ROREG_PTR((void*)u8g2_font_sarasa_m8_chinese)},
1832 // #endif
1833 #ifdef USE_U8G2_SARASA_M10_CHINESE
1834 { "font_sarasa_m10_chinese", ROREG_PTR((void*)u8g2_font_sarasa_m10_chinese)},
1835 #endif
1836 #ifdef USE_U8G2_SARASA_M12_CHINESE
1837 { "font_sarasa_m12_chinese", ROREG_PTR((void*)u8g2_font_sarasa_m12_chinese)},
1838 #endif
1839 #ifdef USE_U8G2_SARASA_M14_CHINESE
1840 { "font_sarasa_m14_chinese", ROREG_PTR((void*)u8g2_font_sarasa_m14_chinese)},
1841 #endif
1842 #ifdef USE_U8G2_SARASA_M16_CHINESE
1843 { "font_sarasa_m16_chinese", ROREG_PTR((void*)u8g2_font_sarasa_m16_chinese)},
1844 #endif
1845 #ifdef USE_U8G2_SARASA_M18_CHINESE
1846 { "font_sarasa_m18_chinese", ROREG_PTR((void*)u8g2_font_sarasa_m18_chinese)},
1847 #endif
1848 #ifdef USE_U8G2_SARASA_M20_CHINESE
1849 { "font_sarasa_m20_chinese", ROREG_PTR((void*)u8g2_font_sarasa_m20_chinese)},
1850 #endif
1851 #ifdef USE_U8G2_SARASA_M22_CHINESE
1852 { "font_sarasa_m22_chinese", ROREG_PTR((void*)u8g2_font_sarasa_m22_chinese)},
1853 #endif
1854 #ifdef USE_U8G2_SARASA_M24_CHINESE
1855 { "font_sarasa_m24_chinese", ROREG_PTR((void*)u8g2_font_sarasa_m24_chinese)},
1856 #endif
1857 #ifdef USE_U8G2_SARASA_M26_CHINESE
1858 { "font_sarasa_m26_chinese", ROREG_PTR((void*)u8g2_font_sarasa_m26_chinese)},
1859 #endif
1860 #ifdef USE_U8G2_SARASA_M28_CHINESE
1861 { "font_sarasa_m28_chinese", ROREG_PTR((void*)u8g2_font_sarasa_m28_chinese)},
1862 #endif
1863 { "set_direction", ROREG_FUNC(l_lcd_set_direction)},
1864 //@const direction_0 int 0°方向命令
1865 { "direction_0", ROREG_INT(0)},
1866 //@const direction_90 int 90°方向命令
1867 { "direction_90", ROREG_INT(1)},
1868 //@const direction_180 int 180°方向命令
1869 { "direction_180", ROREG_INT(2)},
1870 //@const direction_270 int 270°方向命令
1871 { "direction_270", ROREG_INT(3)},
1872 //@const HWID_0 硬件lcd驱动id0 (根据芯片支持选择)
1873 { "HWID_0", ROREG_INT(LUAT_LCD_HW_ID_0)},
1874 //@const WIRE_3_BIT_9_INTERFACE_I 三线spi 9bit 模式I
1875 { "WIRE_3_BIT_9_INTERFACE_I", ROREG_INT(LUAT_LCD_IM_3_WIRE_9_BIT_INTERFACE_I)},
1876 //@const WIRE_4_BIT_8_INTERFACE_I 四线spi 8bit 模式I
1877 { "WIRE_4_BIT_8_INTERFACE_I", ROREG_INT(LUAT_LCD_IM_4_WIRE_8_BIT_INTERFACE_I)},
1878 //@const WIRE_3_BIT_9_INTERFACE_II 三线spi 9bit 模式II
1879 { "WIRE_3_BIT_9_INTERFACE_II", ROREG_INT(LUAT_LCD_IM_3_WIRE_9_BIT_INTERFACE_II)},
1880 //@const WIRE_4_BIT_8_INTERFACE_II 四线spi 8bit 模式II
1881 { "WIRE_4_BIT_8_INTERFACE_II", ROREG_INT(LUAT_LCD_IM_4_WIRE_8_BIT_INTERFACE_II)},
1882 //@const DATA_2_LANE int 双通道模式
1883 { "DATA_2_LANE", ROREG_INT(LUAT_LCD_IM_2_DATA_LANE)},
1884 {NULL, ROREG_INT(0)}
1887 LUAMOD_API int luaopen_lcd( lua_State *L ) {
1888 luat_newlib2(L, reg_lcd);
1889 return 1;