luat_lib_lcd.c 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363
  1. /*
  2. @module lcd
  3. @summary lcd驱动模块
  4. @version 1.0
  5. @date 2021.06.16
  6. */
  7. #include "luat_base.h"
  8. #include "luat_lcd.h"
  9. #include "luat_malloc.h"
  10. #include "luat_zbuff.h"
  11. #include "luat_fs.h"
  12. #define LUAT_LOG_TAG "lcd"
  13. #include "luat_log.h"
  14. #include "u8g2.h"
  15. #include "u8g2_luat_fonts.h"
  16. #include "../qrcode/qrcode.h"
  17. int8_t u8g2_font_decode_get_signed_bits(u8g2_font_decode_t *f, uint8_t cnt);
  18. uint8_t u8g2_font_decode_get_unsigned_bits(u8g2_font_decode_t *f, uint8_t cnt);
  19. extern luat_color_t BACK_COLOR , FORE_COLOR ;
  20. extern const luat_lcd_opts_t lcd_opts_st7735;
  21. extern const luat_lcd_opts_t lcd_opts_st7735v;
  22. extern const luat_lcd_opts_t lcd_opts_st7735s;
  23. extern const luat_lcd_opts_t lcd_opts_st7789;
  24. extern const luat_lcd_opts_t lcd_opts_gc9a01;
  25. extern const luat_lcd_opts_t lcd_opts_gc9106l;
  26. extern const luat_lcd_opts_t lcd_opts_gc9306x;
  27. extern const luat_lcd_opts_t lcd_opts_ili9341;
  28. extern const luat_lcd_opts_t lcd_opts_ili9488;
  29. extern const luat_lcd_opts_t lcd_opts_custom;
  30. typedef struct lcd_reg {
  31. const char *name;
  32. const luat_lcd_opts_t *lcd_opts;
  33. }lcd_reg_t;
  34. static const lcd_reg_t lcd_regs[] = {
  35. {"custom", &lcd_opts_custom}, //0 固定为第零个
  36. {"st7735", &lcd_opts_st7735}, //1
  37. {"st7735v", &lcd_opts_st7735v}, //2
  38. {"st7735s", &lcd_opts_st7735s}, //3
  39. {"st7789", &lcd_opts_st7789}, //4
  40. {"gc9a01", &lcd_opts_gc9a01}, //5
  41. {"gc9106l", &lcd_opts_gc9106l}, //6
  42. {"gc9306x", &lcd_opts_gc9306x}, //7
  43. {"gc9306", &lcd_opts_gc9306x}, //gc9306是gc9306x的别名
  44. {"ili9341", &lcd_opts_ili9341}, //8
  45. {"ili9488", &lcd_opts_ili9488}, //9
  46. {"", NULL} // 最后一个必须是空字符串
  47. };
  48. static luat_lcd_conf_t *default_conf = NULL;
  49. static int dft_conf_lua_ref = 0;
  50. // 所有绘图相关的函数都应该调用本函数
  51. static void lcd_auto_flush(luat_lcd_conf_t *conf) {
  52. #ifndef LUAT_USE_LCD_SDL2
  53. if (conf == NULL || conf->buff == NULL || conf->auto_flush == 0)
  54. return;
  55. #endif
  56. luat_lcd_flush(conf);
  57. }
  58. static luat_color_t lcd_str_fg_color,lcd_str_bg_color;
  59. /*
  60. lcd显示屏初始化
  61. @api lcd.init(tp, args)
  62. @string lcd类型, 当前支持st7789/st7735/st7735v/st7735s/gc9a01/gc9106l/gc9306x/ili9341/custom
  63. @table 附加参数,与具体设备有关,pin_pwr为可选项,可不设置port:spi端口,例如0,1,2...如果为device方式则为"device";pin_dc:lcd数据/命令选择引脚;pin_rst:lcd复位引脚;pin_pwr:lcd背光引脚 可选项,可不设置;direction:lcd屏幕方向 0:0° 1:180° 2:270° 3:90°;w:lcd 水平分辨率;h:lcd 竖直分辨率;xoffset:x偏移(不同屏幕ic 不同屏幕方向会有差异);yoffset:y偏移(不同屏幕ic 不同屏幕方向会有差异)
  64. @userdata spi设备,当port = "device"时有效
  65. @usage
  66. -- 初始化spi0的st7789 注意:lcd初始化之前需要先初始化spi
  67. spi_lcd = spi.deviceSetup(0,20,0,0,8,2000000,spi.MSB,1,1)
  68. log.info("lcd.init",
  69. 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))
  70. */
  71. static int l_lcd_init(lua_State* L) {
  72. size_t len = 0;
  73. luat_lcd_conf_t *conf = luat_heap_malloc(sizeof(luat_lcd_conf_t));
  74. if (conf == NULL) {
  75. LLOGE("out of system memory!!!");
  76. return 0;
  77. }
  78. memset(conf, 0, sizeof(luat_lcd_conf_t)); // 填充0,保证无脏数据
  79. conf->pin_pwr = 255;
  80. if (lua_type(L, 3) == LUA_TUSERDATA){
  81. conf->lcd_spi_device = (luat_spi_device_t*)lua_touserdata(L, 3);
  82. conf->port = LUAT_LCD_SPI_DEVICE;
  83. }
  84. const char* tp = luaL_checklstring(L, 1, &len);
  85. int16_t s_index = -1;//第几个屏幕,-1表示没匹配到
  86. for(int i = 0; i < 100; i++){
  87. if (strlen(lcd_regs[i].name) == 0)
  88. break;
  89. if(strcmp(lcd_regs[i].name,tp) == 0){
  90. s_index = i;
  91. break;
  92. }
  93. }
  94. if (s_index != -1) {
  95. LLOGD("ic support: %s",tp);
  96. if (lua_gettop(L) > 1) {
  97. conf->opts = (struct luat_lcd_opts *)lcd_regs[s_index].lcd_opts;
  98. lua_settop(L, 2); // 丢弃多余的参数
  99. lua_pushstring(L, "port");
  100. int port = lua_gettable(L, 2);
  101. if (conf->port == LUAT_LCD_SPI_DEVICE && port ==LUA_TNUMBER) {
  102. LLOGE("port is not device but find luat_spi_device_t");
  103. goto end;
  104. }else if (conf->port != LUAT_LCD_SPI_DEVICE && LUA_TSTRING == port){
  105. LLOGE("port is device but not find luat_spi_device_t");
  106. goto end;
  107. }else if (LUA_TNUMBER == port) {
  108. conf->port = luaL_checkinteger(L, -1);
  109. }else if (LUA_TSTRING == port){
  110. conf->port = LUAT_LCD_SPI_DEVICE;
  111. }
  112. lua_pop(L, 1);
  113. lua_pushstring(L, "pin_dc");
  114. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  115. conf->pin_dc = luaL_checkinteger(L, -1);
  116. }
  117. lua_pop(L, 1);
  118. lua_pushstring(L, "pin_pwr");
  119. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  120. conf->pin_pwr = luaL_checkinteger(L, -1);
  121. }
  122. lua_pop(L, 1);
  123. lua_pushstring(L, "pin_rst");
  124. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  125. conf->pin_rst = luaL_checkinteger(L, -1);
  126. }
  127. lua_pop(L, 1);
  128. lua_pushstring(L, "direction");
  129. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  130. conf->direction = luaL_checkinteger(L, -1);
  131. }
  132. lua_pop(L, 1);
  133. lua_pushstring(L, "w");
  134. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  135. conf->w = luaL_checkinteger(L, -1);
  136. }
  137. lua_pop(L, 1);
  138. lua_pushstring(L, "h");
  139. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  140. conf->h = luaL_checkinteger(L, -1);
  141. }
  142. lua_pop(L, 1);
  143. conf->buffer_size = (conf->w * conf->h) * 2;
  144. lua_pushstring(L, "xoffset");
  145. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  146. conf->xoffset = luaL_checkinteger(L, -1);
  147. }
  148. lua_pop(L, 1);
  149. lua_pushstring(L, "yoffset");
  150. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  151. conf->yoffset = luaL_checkinteger(L, -1);
  152. }
  153. lua_pop(L, 1);
  154. }
  155. if (s_index == 0){
  156. luat_lcd_custom_t *cst = luat_heap_malloc(sizeof(luat_lcd_custom_t));
  157. lua_pushstring(L, "initcmd");
  158. lua_gettable(L, 2);
  159. if (lua_istable(L, -1)) {
  160. cst->init_cmd_count = lua_rawlen(L, -1);
  161. cst->initcmd = luat_heap_malloc(cst->init_cmd_count * sizeof(uint32_t));
  162. for (size_t i = 1; i <= cst->init_cmd_count; i++){
  163. lua_geti(L, -1, i);
  164. cst->initcmd[i-1] = luaL_checkinteger(L, -1);
  165. lua_pop(L, 1);
  166. }
  167. }else if(lua_isstring(L, -1)){
  168. size_t len,cmd;
  169. const char *fail_name = luaL_checklstring(L, -1, &len);
  170. FILE* fd = (FILE *)luat_fs_fopen(fail_name, "rb");
  171. cst->init_cmd_count = 0;
  172. if (fd){
  173. #define INITCMD_BUFF_SIZE 128
  174. char init_cmd_buff[INITCMD_BUFF_SIZE] ;
  175. cst->initcmd = luat_heap_malloc(sizeof(uint32_t));
  176. while (1) {
  177. memset(init_cmd_buff, 0, INITCMD_BUFF_SIZE);
  178. int readline_len = luat_fs_readline(init_cmd_buff, INITCMD_BUFF_SIZE-1, fd);
  179. if (readline_len < 1)
  180. break;
  181. if (memcmp(init_cmd_buff, "#", 1)==0){
  182. continue;
  183. }
  184. char *token = strtok(init_cmd_buff, ",");
  185. if (sscanf(token,"%x",&cmd) < 1){
  186. continue;
  187. }
  188. cst->init_cmd_count = cst->init_cmd_count + 1;
  189. cst->initcmd = luat_heap_realloc(cst->initcmd,cst->init_cmd_count * sizeof(uint32_t));
  190. cst->initcmd[cst->init_cmd_count-1]=cmd;
  191. while( token != NULL ) {
  192. token = strtok(NULL, ",");
  193. if (sscanf(token,"%x",&cmd) < 1){
  194. break;
  195. }
  196. cst->init_cmd_count = cst->init_cmd_count + 1;
  197. cst->initcmd = luat_heap_realloc(cst->initcmd,cst->init_cmd_count * sizeof(uint32_t));
  198. cst->initcmd[cst->init_cmd_count-1]=cmd;
  199. }
  200. }
  201. cst->initcmd[cst->init_cmd_count]= 0;
  202. luat_fs_fclose(fd);
  203. }else{
  204. LLOGE("init_cmd fail open error");
  205. }
  206. }
  207. lua_pop(L, 1);
  208. conf->userdata = cst;
  209. }
  210. // 默认自动flush,即使没有buff
  211. conf->auto_flush = 1;
  212. #ifdef LUAT_USE_LCD_SDL2
  213. extern const luat_lcd_opts_t lcd_opts_sdl2;
  214. conf->opts = &lcd_opts_sdl2;
  215. #endif
  216. int ret = luat_lcd_init(conf);
  217. if (ret == 0) {
  218. if (dft_conf_lua_ref) {
  219. luaL_unref(L, LUA_REGISTRYINDEX, dft_conf_lua_ref);
  220. }
  221. default_conf = conf;
  222. dft_conf_lua_ref = luaL_ref(L, LUA_REGISTRYINDEX);
  223. }
  224. u8g2_SetFontMode(&(conf->luat_lcd_u8g2), 0);
  225. u8g2_SetFontDirection(&(conf->luat_lcd_u8g2), 0);
  226. lua_pushboolean(L, ret == 0 ? 1 : 0);
  227. // lua_pushlightuserdata(L, conf);
  228. return 1;
  229. }
  230. LLOGE("ic not support: %s",tp);
  231. end:
  232. lua_pushboolean(L, 0);
  233. luat_heap_free(conf);
  234. return 1;
  235. }
  236. /*
  237. 关闭lcd显示屏
  238. @api lcd.close()
  239. @usage
  240. -- 关闭lcd
  241. lcd.close()
  242. */
  243. static int l_lcd_close(lua_State* L) {
  244. int ret = luat_lcd_close(default_conf);
  245. lua_pushboolean(L, ret == 0 ? 1 : 0);
  246. return 1;
  247. }
  248. /*
  249. 开启lcd显示屏背光
  250. @api lcd.on()
  251. @usage
  252. -- 开启lcd显示屏背光
  253. lcd.on()
  254. */
  255. static int l_lcd_display_on(lua_State* L) {
  256. int ret = luat_lcd_display_on(default_conf);
  257. lua_pushboolean(L, ret == 0 ? 1 : 0);
  258. return 1;
  259. }
  260. /*
  261. 关闭lcd显示屏背光
  262. @api lcd.off()
  263. @usage
  264. -- 关闭lcd显示屏背光
  265. lcd.off()
  266. */
  267. static int l_lcd_display_off(lua_State* L) {
  268. int ret = luat_lcd_display_off(default_conf);
  269. lua_pushboolean(L, ret == 0 ? 1 : 0);
  270. return 1;
  271. }
  272. /*
  273. lcd睡眠
  274. @api lcd.sleep()
  275. @usage
  276. -- lcd睡眠
  277. lcd.sleep()
  278. */
  279. static int l_lcd_sleep(lua_State* L) {
  280. int ret = luat_lcd_sleep(default_conf);
  281. lua_pushboolean(L, ret == 0 ? 1 : 0);
  282. return 1;
  283. }
  284. /*
  285. lcd唤醒
  286. @api lcd.wakeup()
  287. @usage
  288. -- lcd唤醒
  289. lcd.wakeup()
  290. */
  291. static int l_lcd_wakeup(lua_State* L) {
  292. int ret = luat_lcd_wakeup(default_conf);
  293. lua_pushboolean(L, ret == 0 ? 1 : 0);
  294. return 1;
  295. }
  296. /*
  297. lcd反显
  298. @api lcd.invon()
  299. @usage
  300. -- lcd反显
  301. lcd.invon()
  302. */
  303. static int l_lcd_inv_on(lua_State* L) {
  304. int ret = luat_lcd_inv_on(default_conf);
  305. lua_pushboolean(L, ret == 0 ? 1 : 0);
  306. return 1;
  307. }
  308. /*
  309. lcd反显关闭
  310. @api lcd.invoff()
  311. @usage
  312. -- lcd反显关闭
  313. lcd.invoff()
  314. */
  315. static int l_lcd_inv_off(lua_State* L) {
  316. int ret = luat_lcd_inv_off(default_conf);
  317. lua_pushboolean(L, ret == 0 ? 1 : 0);
  318. return 1;
  319. }
  320. /*
  321. lcd命令
  322. @api lcd.cmd(cmd)
  323. @int cmd
  324. @usage
  325. -- lcd命令
  326. lcd.cmd(0x21)
  327. */
  328. static int l_lcd_write_cmd(lua_State* L) {
  329. int ret = lcd_write_cmd(default_conf,(const uint8_t)luaL_checkinteger(L, 1));
  330. lua_pushboolean(L, ret == 0 ? 1 : 0);
  331. return 1;
  332. }
  333. /*
  334. lcd数据
  335. @api lcd.data(data)
  336. @int data
  337. @usage
  338. -- lcd数据
  339. lcd.data(0x21)
  340. */
  341. static int l_lcd_write_data(lua_State* L) {
  342. int ret = lcd_write_data(default_conf,(const uint8_t)luaL_checkinteger(L, 1));
  343. lua_pushboolean(L, ret == 0 ? 1 : 0);
  344. return 1;
  345. }
  346. /*
  347. lcd颜色设置
  348. @api lcd.setColor(back,fore)
  349. @int 背景色
  350. @int 前景色
  351. @usage
  352. -- lcd颜色设置
  353. lcd.setColor(0xFFFF,0x0000)
  354. */
  355. static int l_lcd_set_color(lua_State* L) {
  356. luat_color_t back,fore;
  357. back = (luat_color_t)luaL_checkinteger(L, 1);
  358. fore = (luat_color_t)luaL_checkinteger(L, 2);
  359. int ret = luat_lcd_set_color(back, fore);
  360. lua_pushboolean(L, ret == 0 ? 1 : 0);
  361. return 1;
  362. }
  363. /*
  364. lcd颜色填充
  365. @api lcd.draw(x1, y1, x2, y2,color)
  366. @int 左上边缘的X位置.
  367. @int 左上边缘的Y位置.
  368. @int 右上边缘的X位置.
  369. @int 右上边缘的Y位置.
  370. @string 字符串或zbuff对象
  371. @usage
  372. -- lcd颜色填充
  373. local buff = zbuff.create({201,1,16},0x001F)
  374. lcd.draw(20,30,220,30,buff)
  375. */
  376. static int l_lcd_draw(lua_State* L) {
  377. uint16_t x1, y1, x2, y2;
  378. int ret;
  379. // luat_color_t *color = NULL;
  380. luat_zbuff_t *buff;
  381. x1 = luaL_checkinteger(L, 1);
  382. y1 = luaL_checkinteger(L, 2);
  383. x2 = luaL_checkinteger(L, 3);
  384. y2 = luaL_checkinteger(L, 4);
  385. if (lua_isinteger(L, 5)) {
  386. // color = (luat_color_t *)luaL_checkstring(L, 5);
  387. luat_color_t color = (uint32_t)luaL_checkinteger(L, 1);
  388. ret = luat_lcd_draw(default_conf, x1, y1, x2, y2, &color);
  389. }
  390. else if (lua_isuserdata(L, 5)) {
  391. buff = luaL_checkudata(L, 5, LUAT_ZBUFF_TYPE);
  392. luat_color_t *color = (luat_color_t *)buff->addr;
  393. ret = luat_lcd_draw(default_conf, x1, y1, x2, y2, color);
  394. }
  395. else if(lua_isstring(L, 5)) {
  396. luat_color_t *color = (luat_color_t *)luaL_checkstring(L, 5);
  397. ret = luat_lcd_draw(default_conf, x1, y1, x2, y2, color);
  398. }
  399. else {
  400. return 0;
  401. }
  402. lcd_auto_flush(default_conf);
  403. // int ret = luat_lcd_draw(default_conf, x1, y1, x2, y2, color);
  404. lua_pushboolean(L, ret == 0 ? 1 : 0);
  405. return 1;
  406. }
  407. /*
  408. lcd清屏
  409. @api lcd.clear(color)
  410. @int 屏幕颜色 可选参数,默认背景色
  411. @usage
  412. -- lcd清屏
  413. lcd.clear()
  414. */
  415. static int l_lcd_clear(lua_State* L) {
  416. //size_t len = 0;
  417. luat_color_t color = BACK_COLOR;
  418. if (lua_gettop(L) > 0)
  419. color = (uint32_t)luaL_checkinteger(L, 1);
  420. int ret = luat_lcd_clear(default_conf, color);
  421. lcd_auto_flush(default_conf);
  422. lua_pushboolean(L, ret == 0 ? 1 : 0);
  423. return 1;
  424. }
  425. /*
  426. lcd颜色填充
  427. @api lcd.fill(x1, y1, x2, y2,color)
  428. @int 左上边缘的X位置.
  429. @int 左上边缘的Y位置.
  430. @int 右上边缘的X位置.
  431. @int 右上边缘的Y位置.
  432. @int 绘画颜色 可选参数,默认背景色
  433. @usage
  434. -- lcd颜色填充
  435. lcd.fill(20,30,220,30,0x0000)
  436. */
  437. static int l_lcd_draw_fill(lua_State* L) {
  438. uint16_t x1, y1, x2, y2;
  439. luat_color_t color = BACK_COLOR;
  440. x1 = luaL_checkinteger(L, 1);
  441. y1 = luaL_checkinteger(L, 2);
  442. x2 = luaL_checkinteger(L, 3);
  443. y2 = luaL_checkinteger(L, 4);
  444. if (lua_gettop(L) > 4)
  445. color = (luat_color_t)luaL_checkinteger(L, 5);
  446. int ret = luat_lcd_draw_fill(default_conf, x1, y1, x2, y2, color);
  447. lcd_auto_flush(default_conf);
  448. lua_pushboolean(L, ret == 0 ? 1 : 0);
  449. return 1;
  450. }
  451. /*
  452. 画一个点.
  453. @api lcd.drawPoint(x0,y0,color)
  454. @int 点的X位置.
  455. @int 点的Y位置.
  456. @int 绘画颜色 可选参数,默认前景色
  457. @usage
  458. lcd.drawPoint(20,30,0x001F)
  459. */
  460. static int l_lcd_draw_point(lua_State* L) {
  461. uint16_t x, y;
  462. luat_color_t color = FORE_COLOR;
  463. x = luaL_checkinteger(L, 1);
  464. y = luaL_checkinteger(L, 2);
  465. if (lua_gettop(L) > 2)
  466. color = (luat_color_t)luaL_checkinteger(L, 3);
  467. int ret = luat_lcd_draw_point(default_conf, x, y, color);
  468. lcd_auto_flush(default_conf);
  469. lua_pushboolean(L, ret == 0 ? 1 : 0);
  470. return 1;
  471. }
  472. /*
  473. 在两点之间画一条线.
  474. @api lcd.drawLine(x0,y0,x1,y1,color)
  475. @int 第一个点的X位置.
  476. @int 第一个点的Y位置.
  477. @int 第二个点的X位置.
  478. @int 第二个点的Y位置.
  479. @int 绘画颜色 可选参数,默认前景色
  480. @usage
  481. lcd.drawLine(20,30,220,30,0x001F)
  482. */
  483. static int l_lcd_draw_line(lua_State* L) {
  484. uint16_t x1, y1, x2, y2;
  485. luat_color_t color = FORE_COLOR;
  486. x1 = luaL_checkinteger(L, 1);
  487. y1 = luaL_checkinteger(L, 2);
  488. x2 = luaL_checkinteger(L, 3);
  489. y2 = luaL_checkinteger(L, 4);
  490. if (lua_gettop(L) > 4)
  491. color = (luat_color_t)luaL_checkinteger(L, 5);
  492. int ret = luat_lcd_draw_line(default_conf, x1, y1, x2, y2, color);
  493. lcd_auto_flush(default_conf);
  494. lua_pushboolean(L, ret == 0 ? 1 : 0);
  495. return 1;
  496. }
  497. /*
  498. 从x / y位置(左上边缘)开始绘制一个框
  499. @api lcd.drawRectangle(x0,y0,x1,y1,color)
  500. @int 左上边缘的X位置.
  501. @int 左上边缘的Y位置.
  502. @int 右下边缘的X位置.
  503. @int 右下边缘的Y位置.
  504. @int 绘画颜色 可选参数,默认前景色
  505. @usage
  506. lcd.drawRectangle(20,40,220,80,0x001F)
  507. */
  508. static int l_lcd_draw_rectangle(lua_State* L) {
  509. uint16_t x1, y1, x2, y2;
  510. luat_color_t color = FORE_COLOR;
  511. x1 = luaL_checkinteger(L, 1);
  512. y1 = luaL_checkinteger(L, 2);
  513. x2 = luaL_checkinteger(L, 3);
  514. y2 = luaL_checkinteger(L, 4);
  515. if (lua_gettop(L) > 4)
  516. color = (luat_color_t)luaL_checkinteger(L, 5);
  517. int ret = luat_lcd_draw_rectangle(default_conf, x1, y1, x2, y2, color);
  518. lcd_auto_flush(default_conf);
  519. lua_pushboolean(L, ret == 0 ? 1 : 0);
  520. return 1;
  521. }
  522. /*
  523. 从x / y位置(圆心)开始绘制一个圆
  524. @api lcd.drawCircle(x0,y0,r,color)
  525. @int 圆心的X位置.
  526. @int 圆心的Y位置.
  527. @int 半径.
  528. @int 绘画颜色 可选参数,默认前景色
  529. @usage
  530. lcd.drawCircle(120,120,20,0x001F)
  531. */
  532. static int l_lcd_draw_circle(lua_State* L) {
  533. uint16_t x0, y0, r;
  534. luat_color_t color = FORE_COLOR;
  535. x0 = luaL_checkinteger(L, 1);
  536. y0 = luaL_checkinteger(L, 2);
  537. r = luaL_checkinteger(L, 3);
  538. if (lua_gettop(L) > 3)
  539. color = (luat_color_t)luaL_checkinteger(L, 4);
  540. int ret = luat_lcd_draw_circle(default_conf, x0, y0, r, color);
  541. lcd_auto_flush(default_conf);
  542. lua_pushboolean(L, ret == 0 ? 1 : 0);
  543. return 1;
  544. }
  545. /**
  546. 缓冲区绘制QRCode
  547. @api lcd.drawQrcode(x, y, str, version)
  548. @int x坐标
  549. @int y坐标
  550. @string 二维码的内容
  551. @int 二维码版本号 可选1_40 对应21*21到177*177
  552. @return nil 无返回值
  553. */
  554. static int l_lcd_drawQrcode(lua_State *L)
  555. {
  556. size_t len;
  557. int x = luaL_checkinteger(L, 1);
  558. int y = luaL_checkinteger(L, 2);
  559. const char* str = luaL_checklstring(L, 3, &len);
  560. int version = luaL_checkinteger(L, 4);
  561. // Create the QR code
  562. QRCode qrcode;
  563. uint8_t qrcodeData[qrcode_getBufferSize(version)];
  564. qrcode_initText(&qrcode, qrcodeData, version, ECC_LOW, str);
  565. for(int i = 0; i < qrcode.size; i++)
  566. {
  567. for (int j = 0; j < qrcode.size; j++)
  568. {
  569. qrcode_getModule(&qrcode, j, i) ? luat_lcd_draw_point(default_conf, x+j, y+i, FORE_COLOR) : luat_lcd_draw_point(default_conf, x+j, y+i, BACK_COLOR);
  570. }
  571. }
  572. lcd_auto_flush(default_conf);
  573. return 0;
  574. }
  575. static uint8_t utf8_state;
  576. static uint16_t encoding;
  577. static uint16_t utf8_next(uint8_t b)
  578. {
  579. if ( b == 0 ) /* '\n' terminates the string to support the string list procedures */
  580. return 0x0ffff; /* end of string detected, pending UTF8 is discarded */
  581. if ( utf8_state == 0 )
  582. {
  583. if ( b >= 0xfc ) /* 6 byte sequence */
  584. {
  585. utf8_state = 5;
  586. b &= 1;
  587. }
  588. else if ( b >= 0xf8 )
  589. {
  590. utf8_state = 4;
  591. b &= 3;
  592. }
  593. else if ( b >= 0xf0 )
  594. {
  595. utf8_state = 3;
  596. b &= 7;
  597. }
  598. else if ( b >= 0xe0 )
  599. {
  600. utf8_state = 2;
  601. b &= 15;
  602. }
  603. else if ( b >= 0xc0 )
  604. {
  605. utf8_state = 1;
  606. b &= 0x01f;
  607. }
  608. else
  609. {
  610. /* do nothing, just use the value as encoding */
  611. return b;
  612. }
  613. encoding = b;
  614. return 0x0fffe;
  615. }
  616. else
  617. {
  618. utf8_state--;
  619. /* The case b < 0x080 (an illegal UTF8 encoding) is not checked here. */
  620. encoding<<=6;
  621. b &= 0x03f;
  622. encoding |= b;
  623. if ( utf8_state != 0 )
  624. return 0x0fffe; /* nothing to do yet */
  625. }
  626. return encoding;
  627. }
  628. static void u8g2_draw_hv_line(u8g2_t *u8g2, int16_t x, int16_t y, int16_t len, uint8_t dir, uint16_t color){
  629. switch(dir)
  630. {
  631. case 0:
  632. luat_lcd_draw_hline(default_conf,x,y,len,color);
  633. break;
  634. case 1:
  635. luat_lcd_draw_vline(default_conf,x,y,len,color);
  636. break;
  637. case 2:
  638. luat_lcd_draw_hline(default_conf,x-len+1,y,len,color);
  639. break;
  640. case 3:
  641. luat_lcd_draw_vline(default_conf,x,y-len+1,len,color);
  642. break;
  643. }
  644. }
  645. static void u8g2_font_decode_len(u8g2_t *u8g2, uint8_t len, uint8_t is_foreground){
  646. uint8_t cnt; /* total number of remaining pixels, which have to be drawn */
  647. uint8_t rem; /* remaining pixel to the right edge of the glyph */
  648. uint8_t current; /* number of pixels, which need to be drawn for the draw procedure */
  649. /* current is either equal to cnt or equal to rem */
  650. /* local coordinates of the glyph */
  651. uint8_t lx,ly;
  652. /* target position on the screen */
  653. int16_t x, y;
  654. u8g2_font_decode_t *decode = &(u8g2->font_decode);
  655. cnt = len;
  656. /* get the local position */
  657. lx = decode->x;
  658. ly = decode->y;
  659. for(;;){
  660. /* calculate the number of pixel to the right edge of the glyph */
  661. rem = decode->glyph_width;
  662. rem -= lx;
  663. /* calculate how many pixel to draw. This is either to the right edge */
  664. /* or lesser, if not enough pixel are left */
  665. current = rem;
  666. if ( cnt < rem )
  667. current = cnt;
  668. /* now draw the line, but apply the rotation around the glyph target position */
  669. //u8g2_font_decode_draw_pixel(u8g2, lx,ly,current, is_foreground);
  670. // printf("lx:%d,ly:%d,current:%d, is_foreground:%d \r\n",lx,ly,current, is_foreground);
  671. /* get target position */
  672. x = decode->target_x;
  673. y = decode->target_y;
  674. /* apply rotation */
  675. x = u8g2_add_vector_x(x, lx, ly, decode->dir);
  676. y = u8g2_add_vector_y(y, lx, ly, decode->dir);
  677. /* draw foreground and background (if required) */
  678. if ( current > 0 ) /* avoid drawing zero length lines, issue #4 */
  679. {
  680. if ( is_foreground )
  681. {
  682. u8g2_draw_hv_line(u8g2, x, y, current, decode->dir, lcd_str_fg_color);
  683. }
  684. // else if ( decode->is_transparent == 0 )
  685. // {
  686. // u8g2_draw_hv_line(u8g2, x, y, current, decode->dir, lcd_str_bg_color);
  687. // }
  688. }
  689. /* check, whether the end of the run length code has been reached */
  690. if ( cnt < rem )
  691. break;
  692. cnt -= rem;
  693. lx = 0;
  694. ly++;
  695. }
  696. lx += cnt;
  697. decode->x = lx;
  698. decode->y = ly;
  699. }
  700. static void u8g2_font_setup_decode(u8g2_t *u8g2, const uint8_t *glyph_data)
  701. {
  702. u8g2_font_decode_t *decode = &(u8g2->font_decode);
  703. decode->decode_ptr = glyph_data;
  704. decode->decode_bit_pos = 0;
  705. /* 8 Nov 2015, this is already done in the glyph data search procedure */
  706. /*
  707. decode->decode_ptr += 1;
  708. decode->decode_ptr += 1;
  709. */
  710. decode->glyph_width = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_char_width);
  711. decode->glyph_height = u8g2_font_decode_get_unsigned_bits(decode,u8g2->font_info.bits_per_char_height);
  712. }
  713. static int8_t u8g2_font_decode_glyph(u8g2_t *u8g2, const uint8_t *glyph_data){
  714. uint8_t a, b;
  715. int8_t x, y;
  716. int8_t d;
  717. int8_t h;
  718. u8g2_font_decode_t *decode = &(u8g2->font_decode);
  719. u8g2_font_setup_decode(u8g2, glyph_data);
  720. h = u8g2->font_decode.glyph_height;
  721. x = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_x);
  722. y = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_y);
  723. d = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_delta_x);
  724. if ( decode->glyph_width > 0 )
  725. {
  726. decode->target_x = u8g2_add_vector_x(decode->target_x, x, -(h+y), decode->dir);
  727. decode->target_y = u8g2_add_vector_y(decode->target_y, x, -(h+y), decode->dir);
  728. //u8g2_add_vector(&(decode->target_x), &(decode->target_y), x, -(h+y), decode->dir);
  729. /* reset local x/y position */
  730. decode->x = 0;
  731. decode->y = 0;
  732. /* decode glyph */
  733. for(;;){
  734. a = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_0);
  735. b = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_1);
  736. do{
  737. u8g2_font_decode_len(u8g2, a, 0);
  738. u8g2_font_decode_len(u8g2, b, 1);
  739. } while( u8g2_font_decode_get_unsigned_bits(decode, 1) != 0 );
  740. if ( decode->y >= h )
  741. break;
  742. }
  743. }
  744. return d;
  745. }
  746. const uint8_t *u8g2_font_get_glyph_data(u8g2_t *u8g2, uint16_t encoding);
  747. static int16_t u8g2_font_draw_glyph(u8g2_t *u8g2, int16_t x, int16_t y, uint16_t encoding){
  748. int16_t dx = 0;
  749. u8g2->font_decode.target_x = x;
  750. u8g2->font_decode.target_y = y;
  751. const uint8_t *glyph_data = u8g2_font_get_glyph_data(u8g2, encoding);
  752. if ( glyph_data != NULL ){
  753. dx = u8g2_font_decode_glyph(u8g2, glyph_data);
  754. }
  755. return dx;
  756. }
  757. /*
  758. 设置字体
  759. @api lcd.setFont(font)
  760. @int font lcd.font_opposansm8 lcd.font_opposansm10 lcd.font_opposansm16 lcd.font_opposansm18 lcd.font_opposansm20 lcd.font_opposansm22 lcd.font_opposansm24 lcd.font_opposansm32 lcd.font_opposansm12_chinese lcd.font_opposansm16_chinese lcd.font_opposansm24_chinese lcd.font_opposansm32_chinese
  761. @usage
  762. -- 设置为字体,对之后的drawStr有效,调用lcd.drawStr前一定要先设置
  763. -- 使用中文字体需在luat_conf_bsp.h中开启相对应的宏
  764. lcd.setFont(lcd.font_opposansm12)
  765. lcd.drawStr(40,10,"drawStr")
  766. sys.wait(2000)
  767. lcd.setFont(lcd.font_opposansm12_chinese)
  768. lcd.drawStr(40,40,"drawStr测试")
  769. */
  770. static int l_lcd_set_font(lua_State *L) {
  771. if (!lua_islightuserdata(L, 1)) {
  772. LLOGE("only font pointer is allow");
  773. return 0;
  774. }
  775. const uint8_t *ptr = (const uint8_t *)lua_touserdata(L, 1);
  776. if (ptr == NULL) {
  777. LLOGE("only font pointer is allow");
  778. return 0;
  779. }
  780. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), ptr);
  781. lua_pushboolean(L, 1);
  782. return 1;
  783. }
  784. /*
  785. 显示字符串
  786. @api lcd.drawStr(x,y,str,fg_color)
  787. @int x 横坐标
  788. @int y 竖坐标 注意:此(x,y)为左下起始坐标
  789. @string str 文件内容
  790. @int fg_color str颜色 注意:此参数可选,如不填写则使用之前设置的颜色,绘制只会绘制字体部分,背景需要自己清除
  791. @usage
  792. -- 显示之前先设置为中文字体,对之后的drawStr有效,使用中文字体需在luat_conf_bsp.h.h开启#define USE_U8G2_OPPOSANSMxx_CHINESE xx代表字号
  793. lcd.setFont(lcd.font_opposansm12)
  794. lcd.drawStr(40,10,"drawStr")
  795. sys.wait(2000)
  796. lcd.setFont(lcd.font_opposansm16_chinese)
  797. lcd.drawStr(40,40,"drawStr测试")
  798. */
  799. static int l_lcd_draw_str(lua_State* L) {
  800. int x, y;
  801. size_t sz;
  802. const uint8_t* data;
  803. x = luaL_checkinteger(L, 1);
  804. y = luaL_checkinteger(L, 2);
  805. data = (const uint8_t*)luaL_checklstring(L, 3, &sz);
  806. lcd_str_fg_color = (luat_color_t)luaL_optinteger(L, 4,FORE_COLOR);
  807. // lcd_str_bg_color = (uint32_t)luaL_optinteger(L, 5,BACK_COLOR);
  808. if (sz == 0)
  809. return 0;
  810. uint16_t e;
  811. int16_t delta;
  812. utf8_state = 0;
  813. for(;;){
  814. e = utf8_next((uint8_t)*data);
  815. if ( e == 0x0ffff )
  816. break;
  817. data++;
  818. if ( e != 0x0fffe ){
  819. delta = u8g2_font_draw_glyph(&(default_conf->luat_lcd_u8g2), x, y, e);
  820. switch(default_conf->luat_lcd_u8g2.font_decode.dir){
  821. case 0:
  822. x += delta;
  823. break;
  824. case 1:
  825. y += delta;
  826. break;
  827. case 2:
  828. x -= delta;
  829. break;
  830. case 3:
  831. y -= delta;
  832. break;
  833. }
  834. }
  835. }
  836. lcd_auto_flush(default_conf);
  837. return 0;
  838. }
  839. #ifdef LUAT_USE_GTFONT
  840. #include "GT5SLCD2E_1A.h"
  841. extern void gtfont_draw_w(unsigned char *pBits,unsigned int x,unsigned int y,unsigned int widt,unsigned int high,int(*point)(void*),void* userdata,int mode);
  842. 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);
  843. /*
  844. 使用gtfont显示gb2312字符串
  845. @api lcd.drawGtfontGb2312(str,size,x,y)
  846. @string str 显示字符串
  847. @int size 字体大小 (支持16-192号大小字体)
  848. @int x 横坐标
  849. @int y 竖坐标
  850. @usage
  851. lcd.drawGtfontGb2312("啊啊啊",32,0,0)
  852. */
  853. static int l_lcd_draw_gtfont_gb2312(lua_State *L) {
  854. unsigned char buf[128];
  855. size_t len;
  856. int i = 0;
  857. uint8_t strhigh,strlow ;
  858. uint16_t str;
  859. const char *fontCode = luaL_checklstring(L, 1,&len);
  860. unsigned char size = luaL_checkinteger(L, 2);
  861. int x = luaL_checkinteger(L, 3);
  862. int y = luaL_checkinteger(L, 4);
  863. while ( i < len){
  864. strhigh = *fontCode;
  865. fontCode++;
  866. strlow = *fontCode;
  867. str = (strhigh<<8)|strlow;
  868. fontCode++;
  869. int font_size = get_font(buf, 1, str, size, size, size);
  870. if(font_size != size){
  871. LLOGW("get gtfont error");
  872. return 0;
  873. }
  874. gtfont_draw_w(buf , x ,y , size , size,luat_lcd_draw_point,default_conf,0);
  875. x+=size;
  876. i+=2;
  877. }
  878. lcd_auto_flush(default_conf);
  879. return 0;
  880. }
  881. /*
  882. 使用gtfont灰度显示gb2312字符串
  883. @api lcd.drawGtfontGb2312Gray(str,size,gray,x,y)
  884. @string str 显示字符串
  885. @int size 字体大小 (支持16-192号大小字体)
  886. @int gray 灰度[1阶/2阶/3阶/4阶]
  887. @int x 横坐标
  888. @int y 竖坐标
  889. @usage
  890. lcd.drawGtfontGb2312Gray("啊啊啊",32,4,0,40)
  891. */
  892. static int l_lcd_draw_gtfont_gb2312_gray(lua_State* L) {
  893. unsigned char buf[2048];
  894. size_t len;
  895. int i = 0;
  896. uint8_t strhigh,strlow ;
  897. uint16_t str;
  898. const char *fontCode = luaL_checklstring(L, 1,&len);
  899. unsigned char size = luaL_checkinteger(L, 2);
  900. unsigned char font_g = luaL_checkinteger(L, 3);
  901. int x = luaL_checkinteger(L, 4);
  902. int y = luaL_checkinteger(L, 5);
  903. while ( i < len){
  904. strhigh = *fontCode;
  905. fontCode++;
  906. strlow = *fontCode;
  907. str = (strhigh<<8)|strlow;
  908. fontCode++;
  909. int font_size = get_font(buf, 1, str, size*font_g, size*font_g, size*font_g);
  910. if(font_size != size*font_g){
  911. LLOGW("get gtfont error");
  912. return 0;
  913. }
  914. Gray_Process(buf,size,size,font_g);
  915. gtfont_draw_gray_hz(buf, x, y, size , size, font_g, 1,luat_lcd_draw_point,default_conf,0);
  916. x+=size;
  917. i+=2;
  918. }
  919. lcd_auto_flush(default_conf);
  920. return 0;
  921. }
  922. #ifdef LUAT_USE_GTFONT_UTF8
  923. extern unsigned short unicodetogb2312 ( unsigned short chr);
  924. /*
  925. 使用gtfont显示UTF8字符串
  926. @api lcd.drawGtfontUtf8(str,size,x,y)
  927. @string str 显示字符串
  928. @int size 字体大小 (支持16-192号大小字体)
  929. @int x 横坐标
  930. @int y 竖坐标
  931. @usage
  932. lcd.drawGtfontUtf8("啊啊啊",32,0,0)
  933. */
  934. static int l_lcd_draw_gtfont_utf8(lua_State *L) {
  935. unsigned char buf[128];
  936. size_t len;
  937. int i = 0;
  938. uint8_t strhigh,strlow ;
  939. uint16_t e,str;
  940. const char *fontCode = luaL_checklstring(L, 1,&len);
  941. unsigned char size = luaL_checkinteger(L, 2);
  942. int x = luaL_checkinteger(L, 3);
  943. int y = luaL_checkinteger(L, 4);
  944. for(;;){
  945. e = utf8_next((uint8_t)*fontCode);
  946. if ( e == 0x0ffff )
  947. break;
  948. fontCode++;
  949. if ( e != 0x0fffe ){
  950. uint16_t str = unicodetogb2312(e);
  951. int font_size = get_font(buf, 1, str, size, size, size);
  952. if(font_size != size){
  953. LLOGW("get gtfont error");
  954. return 0;
  955. }
  956. gtfont_draw_w(buf , x ,y , size , size,luat_lcd_draw_point,default_conf,0);
  957. x+=size;
  958. }
  959. }
  960. lcd_auto_flush(default_conf);
  961. return 0;
  962. }
  963. /*
  964. 使用gtfont灰度显示UTF8字符串
  965. @api lcd.drawGtfontUtf8Gray(str,size,gray,x,y)
  966. @string str 显示字符串
  967. @int size 字体大小 (支持16-192号大小字体)
  968. @int gray 灰度[1阶/2阶/3阶/4阶]
  969. @int x 横坐标
  970. @int y 竖坐标
  971. @usage
  972. lcd.drawGtfontUtf8Gray("啊啊啊",32,4,0,40)
  973. */
  974. static int l_lcd_draw_gtfont_utf8_gray(lua_State* L) {
  975. unsigned char buf[2048];
  976. size_t len;
  977. int i = 0;
  978. uint8_t strhigh,strlow ;
  979. uint16_t e,str;
  980. const char *fontCode = luaL_checklstring(L, 1,&len);
  981. unsigned char size = luaL_checkinteger(L, 2);
  982. unsigned char font_g = luaL_checkinteger(L, 3);
  983. int x = luaL_checkinteger(L, 4);
  984. int y = luaL_checkinteger(L, 5);
  985. for(;;){
  986. e = utf8_next((uint8_t)*fontCode);
  987. if ( e == 0x0ffff )
  988. break;
  989. fontCode++;
  990. if ( e != 0x0fffe ){
  991. uint16_t str = unicodetogb2312(e);
  992. int font_size = get_font(buf, 1, str, size*font_g, size*font_g, size*font_g);
  993. if(font_size != size*font_g){
  994. LLOGW("get gtfont error");
  995. return 0;
  996. }
  997. Gray_Process(buf,size,size,font_g);
  998. gtfont_draw_gray_hz(buf, x, y, size , size, font_g, 1,luat_lcd_draw_point,default_conf,0);
  999. x+=size;
  1000. }
  1001. }
  1002. lcd_auto_flush(default_conf);
  1003. return 0;
  1004. }
  1005. #endif // LUAT_USE_GTFONT_UTF8
  1006. #endif // LUAT_USE_GTFONT
  1007. static int l_lcd_set_default(lua_State *L) {
  1008. if (lua_gettop(L) == 1) {
  1009. default_conf = lua_touserdata(L, 1);
  1010. lua_pushboolean(L, 1);
  1011. return 1;
  1012. }
  1013. return 1;
  1014. }
  1015. static int l_lcd_get_default(lua_State *L) {
  1016. if (default_conf == NULL)
  1017. return 0;
  1018. lua_pushlightuserdata(L, default_conf);
  1019. return 1;
  1020. }
  1021. /*
  1022. 获取屏幕尺寸
  1023. @api lcd.getSize()
  1024. @return int 宽, 如果未初始化会返回0
  1025. @return int 高, 如果未初始化会返回0
  1026. @usage
  1027. log.info("lcd", "size", lcd.getSize())
  1028. */
  1029. static int l_lcd_get_size(lua_State *L) {
  1030. if (lua_gettop(L) == 1) {
  1031. luat_lcd_conf_t * conf = lua_touserdata(L, 1);
  1032. if (conf) {
  1033. lua_pushinteger(L, conf->w);
  1034. lua_pushinteger(L, conf->h);
  1035. return 2;
  1036. }
  1037. }
  1038. if (default_conf == NULL) {
  1039. lua_pushinteger(L, 0);
  1040. lua_pushinteger(L, 0);
  1041. }
  1042. else {
  1043. lua_pushinteger(L, default_conf->w);
  1044. lua_pushinteger(L, default_conf->h);
  1045. }
  1046. return 2;
  1047. }
  1048. static void lcd_DrawHXBM(uint16_t x, uint16_t y, uint16_t len, const uint8_t *b){
  1049. uint8_t mask;
  1050. mask = 1;
  1051. while(len > 0) {
  1052. if ( *b & mask ) luat_lcd_draw_hline(default_conf, x, y, 1,FORE_COLOR);
  1053. else luat_lcd_draw_vline(default_conf, x, y, 1,BACK_COLOR);
  1054. x++;
  1055. mask <<= 1;
  1056. if ( mask == 0 ){
  1057. mask = 1;
  1058. b++;
  1059. }
  1060. len--;
  1061. }
  1062. }
  1063. /*
  1064. 绘制位图
  1065. @api lcd.drawXbm(x, y, w, h, data)
  1066. @int X坐标
  1067. @int y坐标
  1068. @int 位图宽
  1069. @int 位图高
  1070. @int 位图数据,每一位代表一个像素
  1071. @usage
  1072. -- 取模使用PCtoLCD2002软件即可
  1073. -- 在(0,0)为左上角,绘制 16x16 "今" 的位图
  1074. lcd.drawXbm(0, 0, 16,16, string.char(
  1075. 0x80,0x00,0x80,0x00,0x40,0x01,0x20,0x02,0x10,0x04,0x48,0x08,0x84,0x10,0x83,0x60,
  1076. 0x00,0x00,0xF8,0x0F,0x00,0x08,0x00,0x04,0x00,0x04,0x00,0x02,0x00,0x01,0x80,0x00
  1077. ))
  1078. */
  1079. static int l_lcd_drawxbm(lua_State *L){
  1080. int x = luaL_checkinteger(L, 1);
  1081. int y = luaL_checkinteger(L, 2);
  1082. int w = luaL_checkinteger(L, 3);
  1083. int h = luaL_checkinteger(L, 4);
  1084. size_t len = 0;
  1085. const char* data = luaL_checklstring(L, 5, &len);
  1086. if (h < 1) return 0; // 行数必须大于0
  1087. if (w < h) return 0; // 起码要填满一行
  1088. uint8_t blen;
  1089. blen = w;
  1090. blen += 7;
  1091. blen >>= 3;
  1092. while( h > 0 ){
  1093. lcd_DrawHXBM(x, y, w, (const uint8_t*)data);
  1094. data += blen;
  1095. y++;
  1096. h--;
  1097. }
  1098. lcd_auto_flush(default_conf);
  1099. lua_pushboolean(L, 1);
  1100. return 1;
  1101. }
  1102. #ifdef LUAT_USE_TJPGD
  1103. #include "luat_tjpgd.h"
  1104. /*
  1105. 显示图片,当前只支持jpg,jpeg
  1106. @api lcd.showImage(x, y, file)
  1107. @int X坐标
  1108. @int y坐标
  1109. @string 文件路径
  1110. @usage
  1111. lcd.showImage(0,0,"/luadb/logo.jpg")
  1112. */
  1113. static int l_lcd_showimage(lua_State *L){
  1114. size_t size = 0;
  1115. int x = luaL_checkinteger(L, 1);
  1116. int y = luaL_checkinteger(L, 2);
  1117. const char* input_file = luaL_checklstring(L, 3, &size);
  1118. 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){
  1119. luat_tjpgd_data_t* image_data = luat_tjpgd(input_file);
  1120. if(image_data->fbuf != NULL){
  1121. luat_lcd_show_image(default_conf,x, y, image_data->width, image_data->height, (luat_color_t *)image_data->fbuf,1);
  1122. luat_heap_free(image_data->fbuf); /* Discard frame buffer */
  1123. luat_heap_free(image_data); /* Discard frame buffer */
  1124. lcd_auto_flush(default_conf);
  1125. lua_pushboolean(L, 1);
  1126. }
  1127. else {
  1128. lua_pushboolean(L, 0);
  1129. }
  1130. }else{
  1131. LLOGE("input_file not support");
  1132. lua_pushboolean(L, 0);
  1133. }
  1134. return 1;
  1135. }
  1136. #endif
  1137. /*
  1138. 主动刷新数据到界面, 仅设置buff且禁用自动属性后使用
  1139. @api lcd.flush()
  1140. @return bool 成功返回true, 否则返回nil/false
  1141. @usgae
  1142. -- 本API与 lcd.setupBuff lcd.autoFlush 配合使用
  1143. lcd.flush()
  1144. */
  1145. static int l_lcd_flush(lua_State* L) {
  1146. luat_lcd_conf_t * conf = NULL;
  1147. if (lua_gettop(L) == 1) {
  1148. conf = lua_touserdata(L, 1);
  1149. }
  1150. else {
  1151. conf = default_conf;
  1152. }
  1153. if (conf == NULL) {
  1154. //LLOGW("lcd not init");
  1155. return 0;
  1156. }
  1157. if (conf-> buff) {
  1158. //LLOGW("lcd without buff, not support flush");
  1159. return 0;
  1160. }
  1161. if (conf->auto_flush) {
  1162. //LLOGI("lcd auto flush is enable, no need for flush");
  1163. return 0;
  1164. }
  1165. luat_lcd_flush(conf);
  1166. lua_pushboolean(L, 1);
  1167. return 0;
  1168. }
  1169. /*
  1170. 设置显示缓冲区, 所需内存大小为 2*宽*高 字节. 请衡量内存需求与业务所需的刷新频次.
  1171. @api lcd.setupBuff()
  1172. @return bool 是否成功
  1173. @usage
  1174. -- 初始化lcd的buff缓冲区, 可理解为FrameBuffer区域.
  1175. lcd.setupBuff()
  1176. */
  1177. static int l_lcd_setup_buff(lua_State* L) {
  1178. luat_lcd_conf_t * conf = NULL;
  1179. if (lua_gettop(L) == 1) {
  1180. conf = lua_touserdata(L, 1);
  1181. }
  1182. else {
  1183. conf = default_conf;
  1184. }
  1185. if (conf == NULL) {
  1186. LLOGW("lcd not init");
  1187. return 0;
  1188. }
  1189. if (conf->buff != NULL) {
  1190. LLOGW("lcd buff is ok");
  1191. return 0;
  1192. }
  1193. conf->buff = luat_heap_malloc(sizeof(luat_color_t) * conf->w * conf->h);
  1194. if (conf->buff == NULL) {
  1195. LLOGE("lcd buff malloc fail, out of memory?");
  1196. return 0;
  1197. }
  1198. lua_pushboolean(L, 1);
  1199. return 1;
  1200. }
  1201. /*
  1202. 设置自动刷新, 需配合lcd.setupBuff使用
  1203. @api lcd.autoFlush(enable)
  1204. @bool 是否自动刷新,默认为true
  1205. @usage
  1206. -- 设置buff 并禁用自动更新
  1207. lcd.setupBuff()
  1208. lcd.autoFlush(false)
  1209. -- 禁止自动更新后, 需要使用 lcd.flush() 主动刷新数据到屏幕
  1210. */
  1211. static int l_lcd_auto_flush(lua_State* L) {
  1212. luat_lcd_conf_t * conf = default_conf;
  1213. if (conf == NULL) {
  1214. LLOGW("lcd not init");
  1215. return 0;
  1216. }
  1217. conf->auto_flush = lua_toboolean(L, 1);
  1218. lua_pushboolean(L, conf->auto_flush);
  1219. return 1;
  1220. }
  1221. #include "rotable2.h"
  1222. static const rotable_Reg_t reg_lcd[] =
  1223. {
  1224. { "init", ROREG_FUNC(l_lcd_init)},
  1225. { "clear", ROREG_FUNC(l_lcd_clear)},
  1226. { "fill", ROREG_FUNC(l_lcd_draw_fill)},
  1227. { "drawPoint", ROREG_FUNC(l_lcd_draw_point)},
  1228. { "drawLine", ROREG_FUNC(l_lcd_draw_line)},
  1229. { "drawRectangle", ROREG_FUNC(l_lcd_draw_rectangle)},
  1230. { "drawCircle", ROREG_FUNC(l_lcd_draw_circle)},
  1231. { "drawQrcode", ROREG_FUNC(l_lcd_drawQrcode)},
  1232. { "drawStr", ROREG_FUNC(l_lcd_draw_str)},
  1233. { "flush", ROREG_FUNC(l_lcd_flush)},
  1234. { "setupBuff", ROREG_FUNC(l_lcd_setup_buff)},
  1235. { "autoFlush", ROREG_FUNC(l_lcd_auto_flush)},
  1236. { "setFont", ROREG_FUNC(l_lcd_set_font)},
  1237. { "setDefault", ROREG_FUNC(l_lcd_set_default)},
  1238. { "getDefault", ROREG_FUNC(l_lcd_get_default)},
  1239. { "getSize", ROREG_FUNC(l_lcd_get_size)},
  1240. { "drawXbm", ROREG_FUNC(l_lcd_drawxbm)},
  1241. { "close", ROREG_FUNC(l_lcd_close)},
  1242. { "on", ROREG_FUNC(l_lcd_display_on)},
  1243. { "off", ROREG_FUNC(l_lcd_display_off)},
  1244. { "sleep", ROREG_FUNC(l_lcd_sleep)},
  1245. { "wakeup", ROREG_FUNC(l_lcd_wakeup)},
  1246. { "invon", ROREG_FUNC(l_lcd_inv_on)},
  1247. { "invoff", ROREG_FUNC(l_lcd_inv_off)},
  1248. { "cmd", ROREG_FUNC(l_lcd_write_cmd)},
  1249. { "data", ROREG_FUNC(l_lcd_write_data)},
  1250. { "setColor", ROREG_FUNC(l_lcd_set_color)},
  1251. { "draw", ROREG_FUNC(l_lcd_draw)},
  1252. #ifdef LUAT_USE_TJPGD
  1253. { "showImage", ROREG_FUNC(l_lcd_showimage)},
  1254. #endif
  1255. #ifdef LUAT_USE_GTFONT
  1256. { "drawGtfontGb2312", ROREG_FUNC(l_lcd_draw_gtfont_gb2312)},
  1257. { "drawGtfontGb2312Gray", ROREG_FUNC(l_lcd_draw_gtfont_gb2312_gray)},
  1258. #ifdef LUAT_USE_GTFONT_UTF8
  1259. { "drawGtfontUtf8", ROREG_FUNC(l_lcd_draw_gtfont_utf8)},
  1260. { "drawGtfontUtf8Gray", ROREG_FUNC(l_lcd_draw_gtfont_utf8_gray)},
  1261. #endif // LUAT_USE_GTFONT_UTF8
  1262. #endif // LUAT_USE_GTFONT
  1263. { "font_unifont_t_symbols", ROREG_PTR((void*)u8g2_font_unifont_t_symbols)},
  1264. { "font_open_iconic_weather_6x_t", ROREG_PTR((void*)u8g2_font_open_iconic_weather_6x_t)},
  1265. { "font_opposansm8", ROREG_PTR((void*)u8g2_font_opposansm8)},
  1266. { "font_opposansm10", ROREG_PTR((void*)u8g2_font_opposansm10)},
  1267. { "font_opposansm12", ROREG_PTR((void*)u8g2_font_opposansm12)},
  1268. { "font_opposansm16", ROREG_PTR((void*)u8g2_font_opposansm16)},
  1269. { "font_opposansm18", ROREG_PTR((void*)u8g2_font_opposansm18)},
  1270. { "font_opposansm20", ROREG_PTR((void*)u8g2_font_opposansm20)},
  1271. { "font_opposansm22", ROREG_PTR((void*)u8g2_font_opposansm22)},
  1272. { "font_opposansm24", ROREG_PTR((void*)u8g2_font_opposansm24)},
  1273. { "font_opposansm32", ROREG_PTR((void*)u8g2_font_opposansm32)},
  1274. #ifdef USE_U8G2_OPPOSANSM12_CHINESE
  1275. { "font_opposansm12_chinese", ROREG_PTR((void*)u8g2_font_opposansm12_chinese)},
  1276. #endif
  1277. #ifdef USE_U8G2_OPPOSANSM16_CHINESE
  1278. { "font_opposansm16_chinese", ROREG_PTR((void*)u8g2_font_opposansm16_chinese)},
  1279. #endif
  1280. #ifdef USE_U8G2_OPPOSANSM24_CHINESE
  1281. { "font_opposansm24_chinese", ROREG_PTR((void*)u8g2_font_opposansm24_chinese)},
  1282. #endif
  1283. #ifdef USE_U8G2_OPPOSANSM32_CHINESE
  1284. { "font_opposansm32_chinese", ROREG_PTR((void*)u8g2_font_opposansm32_chinese)},
  1285. #endif
  1286. {NULL, ROREG_INT(0)}
  1287. };
  1288. LUAMOD_API int luaopen_lcd( lua_State *L ) {
  1289. luat_newlib2(L, reg_lcd);
  1290. return 1;
  1291. }