luat_lib_lcd.c 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014
  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_spi.h"
  12. #define LUAT_LOG_TAG "lcd"
  13. #include "luat_log.h"
  14. enum
  15. {
  16. font_opposansm8,
  17. font_opposansm10,
  18. font_opposansm12,
  19. font_opposansm16,
  20. font_opposansm18,
  21. font_opposansm20,
  22. font_opposansm22,
  23. font_opposansm24,
  24. font_opposansm32,
  25. font_opposansm12_chinese,
  26. font_opposansm16_chinese,
  27. font_opposansm24_chinese,
  28. font_opposansm32_chinese,
  29. };
  30. extern uint32_t BACK_COLOR , FORE_COLOR ;
  31. extern const luat_lcd_opts_t lcd_opts_st7735;
  32. extern const luat_lcd_opts_t lcd_opts_st7735s;
  33. extern const luat_lcd_opts_t lcd_opts_st7789;
  34. extern const luat_lcd_opts_t lcd_opts_gc9a01;
  35. extern const luat_lcd_opts_t lcd_opts_gc9106l;
  36. extern const luat_lcd_opts_t lcd_opts_gc9306;
  37. extern const luat_lcd_opts_t lcd_opts_ili9341;
  38. extern const luat_lcd_opts_t lcd_opts_custom;
  39. static luat_lcd_conf_t *default_conf = NULL;
  40. static uint32_t lcd_str_fg_color,lcd_str_bg_color;
  41. /*
  42. lcd显示屏初始化
  43. @api lcd.init(tp, args)
  44. @string lcd类型, 当前支持st7789/st7735/st7735s/gc9a01/gc9106l/gc9306/ili9341/custom
  45. @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 不同屏幕方向会有差异)
  46. @userdata spi设备,当port = "device"时有效
  47. @usage
  48. -- 初始化spi0的st7789 注意:lcd初始化之前需要先初始化spi
  49. local spi_lcd = spi.deviceSetup(0,20,0,0,8,2000000,spi.MSB,1,1)
  50. log.info("lcd.init",
  51. 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))
  52. */
  53. static int l_lcd_init(lua_State* L) {
  54. size_t len = 0;
  55. luat_lcd_conf_t *conf = luat_heap_malloc(sizeof(luat_lcd_conf_t));
  56. memset(conf, 0, sizeof(luat_lcd_conf_t)); // 填充0,保证无脏数据
  57. conf->pin_pwr = 255;
  58. if (lua_type(L, 3) == LUA_TUSERDATA){
  59. conf->userdata = (luat_spi_device_t*)lua_touserdata(L, 3);
  60. conf->port = LUAT_LCD_SPI_DEVICE;
  61. }
  62. const char* tp = luaL_checklstring(L, 1, &len);
  63. if (!strcmp("st7735", tp) || !strcmp("st7789", tp) || !strcmp("st7735s", tp)
  64. || !strcmp("gc9a01", tp) || !strcmp("gc9106l", tp)
  65. || !strcmp("gc9306", tp) || !strcmp("ili9341", tp)
  66. || !strcmp("custom", tp)) {
  67. if (lua_gettop(L) > 1) {
  68. lua_settop(L, 2); // 丢弃多余的参数
  69. lua_pushstring(L, "port");
  70. int port = lua_gettable(L, 2);
  71. if (conf->port == LUAT_LCD_SPI_DEVICE && port ==LUA_TNUMBER) {
  72. LLOGE("port is not device but find luat_spi_device_t");
  73. goto end;
  74. }else if (conf->port != LUAT_LCD_SPI_DEVICE && LUA_TSTRING == port){
  75. LLOGE("port is device but not find luat_spi_device_t");
  76. goto end;
  77. }else if (LUA_TNUMBER == port) {
  78. conf->port = luaL_checkinteger(L, -1);
  79. }else if (LUA_TSTRING == port){
  80. conf->port = LUAT_LCD_SPI_DEVICE;
  81. }
  82. lua_pop(L, 1);
  83. lua_pushstring(L, "pin_dc");
  84. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  85. conf->pin_dc = luaL_checkinteger(L, -1);
  86. }
  87. lua_pop(L, 1);
  88. lua_pushstring(L, "pin_pwr");
  89. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  90. conf->pin_pwr = luaL_checkinteger(L, -1);
  91. }
  92. lua_pop(L, 1);
  93. lua_pushstring(L, "pin_rst");
  94. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  95. conf->pin_rst = luaL_checkinteger(L, -1);
  96. }
  97. lua_pop(L, 1);
  98. lua_pushstring(L, "direction");
  99. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  100. conf->direction = luaL_checkinteger(L, -1);
  101. }
  102. lua_pop(L, 1);
  103. lua_pushstring(L, "w");
  104. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  105. conf->w = luaL_checkinteger(L, -1);
  106. }
  107. lua_pop(L, 1);
  108. lua_pushstring(L, "h");
  109. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  110. conf->h = luaL_checkinteger(L, -1);
  111. }
  112. lua_pop(L, 1);
  113. lua_pushstring(L, "xoffset");
  114. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  115. conf->xoffset = luaL_checkinteger(L, -1);
  116. }
  117. lua_pop(L, 1);
  118. lua_pushstring(L, "yoffset");
  119. if (LUA_TNUMBER == lua_gettable(L, 2)) {
  120. conf->yoffset = luaL_checkinteger(L, -1);
  121. }
  122. lua_pop(L, 1);
  123. }
  124. if (!strcmp("st7735", tp))
  125. conf->opts = (luat_lcd_opts_t*)&lcd_opts_st7735;
  126. else if (!strcmp("st7735s", tp))
  127. conf->opts = (luat_lcd_opts_t*)&lcd_opts_st7735s;
  128. else if (!strcmp("st7789", tp))
  129. conf->opts = (luat_lcd_opts_t*)&lcd_opts_st7789;
  130. else if (!strcmp("gc9a01", tp))
  131. conf->opts = (luat_lcd_opts_t*)&lcd_opts_gc9a01;
  132. else if (!strcmp("gc9106l", tp))
  133. conf->opts = (luat_lcd_opts_t*)&lcd_opts_gc9106l;
  134. else if (!strcmp("gc9306", tp))
  135. conf->opts = (luat_lcd_opts_t*)&lcd_opts_gc9306;
  136. else if (!strcmp("ili9341", tp))
  137. conf->opts = (luat_lcd_opts_t*)&lcd_opts_ili9341;
  138. else if (!strcmp("custom", tp)) {
  139. conf->opts = (luat_lcd_opts_t*)&lcd_opts_custom;
  140. luat_lcd_custom_t *cst = luat_heap_malloc(sizeof(luat_lcd_custom_t));
  141. // 获取initcmd/sleepcmd/wakecmd
  142. lua_pushstring(L, "sleepcmd");
  143. lua_gettable(L, 2);
  144. cst->sleepcmd = luaL_checkinteger(L, -1);
  145. lua_pop(L, 1);
  146. lua_pushstring(L, "wakecmd");
  147. lua_gettable(L, 2);
  148. cst->wakecmd = luaL_checkinteger(L, -1);
  149. lua_pop(L, 1);
  150. lua_pushstring(L, "initcmd");
  151. lua_gettable(L, 2);
  152. cst->init_cmd_count = lua_rawlen(L, -1);
  153. luat_heap_realloc(cst, sizeof(luat_lcd_custom_t) + cst->init_cmd_count * 4);
  154. for (size_t i = 1; i <= cst->init_cmd_count; i++)
  155. {
  156. lua_geti(L, -1, i);
  157. cst->initcmd[i-1] = luaL_checkinteger(L, -1);
  158. lua_pop(L, 1);
  159. }
  160. lua_pop(L, 1);
  161. }
  162. int ret = luat_lcd_init(conf);
  163. lua_pushboolean(L, ret == 0 ? 1 : 0);
  164. if (ret == 0)
  165. default_conf = conf;
  166. u8g2_SetFontMode(&(default_conf->luat_lcd_u8g2), 0);
  167. u8g2_SetFontDirection(&(default_conf->luat_lcd_u8g2), 0);
  168. // lua_pushlightuserdata(L, conf);
  169. return 1;
  170. }
  171. end:
  172. lua_pushboolean(L, 0);
  173. luat_heap_free(conf);
  174. return 1;
  175. }
  176. /*
  177. 关闭lcd显示屏
  178. @api lcd.close()
  179. @usage
  180. -- 关闭lcd
  181. lcd.close()
  182. */
  183. static int l_lcd_close(lua_State* L) {
  184. int ret = luat_lcd_close(default_conf);
  185. lua_pushboolean(L, ret == 0 ? 1 : 0);
  186. return 1;
  187. }
  188. /*
  189. 开启lcd显示屏背光
  190. @api lcd.on()
  191. @usage
  192. -- 开启lcd显示屏背光
  193. lcd.on()
  194. */
  195. static int l_lcd_display_on(lua_State* L) {
  196. int ret = luat_lcd_display_on(default_conf);
  197. lua_pushboolean(L, ret == 0 ? 1 : 0);
  198. return 1;
  199. }
  200. /*
  201. 关闭lcd显示屏背光
  202. @api lcd.off()
  203. @usage
  204. -- 关闭lcd显示屏背光
  205. lcd.off()
  206. */
  207. static int l_lcd_display_off(lua_State* L) {
  208. int ret = luat_lcd_display_off(default_conf);
  209. lua_pushboolean(L, ret == 0 ? 1 : 0);
  210. return 1;
  211. }
  212. /*
  213. lcd睡眠
  214. @api lcd.sleep()
  215. @usage
  216. -- lcd睡眠
  217. lcd.sleep()
  218. */
  219. static int l_lcd_sleep(lua_State* L) {
  220. int ret = luat_lcd_sleep(default_conf);
  221. lua_pushboolean(L, ret == 0 ? 1 : 0);
  222. return 1;
  223. }
  224. /*
  225. lcd唤醒
  226. @api lcd.wakeup()
  227. @usage
  228. -- lcd唤醒
  229. lcd.wakeup()
  230. */
  231. static int l_lcd_wakeup(lua_State* L) {
  232. int ret = luat_lcd_wakeup(default_conf);
  233. lua_pushboolean(L, ret == 0 ? 1 : 0);
  234. return 1;
  235. }
  236. /*
  237. lcd颜色设置
  238. @api lcd.setColor(back,fore)
  239. @int 背景色
  240. @int 前景色
  241. @usage
  242. -- lcd颜色设置
  243. lcd.setColor(0xFFFF,0x0000)
  244. */
  245. static int l_lcd_set_color(lua_State* L) {
  246. uint32_t back,fore;
  247. back = (uint32_t)luaL_checkinteger(L, 1);
  248. fore = (uint32_t)luaL_checkinteger(L, 2);
  249. int ret = luat_lcd_set_color(back, fore);
  250. lua_pushboolean(L, ret == 0 ? 1 : 0);
  251. return 1;
  252. }
  253. /*
  254. lcd颜色填充
  255. @api lcd.draw(x1, y1, x2, y2,color)
  256. @int 左上边缘的X位置.
  257. @int 左上边缘的Y位置.
  258. @int 右上边缘的X位置.
  259. @int 右上边缘的Y位置.
  260. @string 字符串或zbuff对象
  261. @usage
  262. -- lcd颜色填充
  263. local buff = zbuff.create({201,1,16},0x001F)
  264. lcd.draw(20,30,220,30,buff)
  265. */
  266. static int l_lcd_draw(lua_State* L) {
  267. uint16_t x1, y1, x2, y2;
  268. int ret;
  269. // luat_color_t *color = NULL;
  270. luat_zbuff_t *buff;
  271. x1 = luaL_checkinteger(L, 1);
  272. y1 = luaL_checkinteger(L, 2);
  273. x2 = luaL_checkinteger(L, 3);
  274. y2 = luaL_checkinteger(L, 4);
  275. if (lua_isinteger(L, 5)) {
  276. // color = (luat_color_t *)luaL_checkstring(L, 5);
  277. uint32_t color = (uint32_t)luaL_checkinteger(L, 1);
  278. ret = luat_lcd_draw(default_conf, x1, y1, x2, y2, &color);
  279. }
  280. else if (lua_isuserdata(L, 5)) {
  281. buff = luaL_checkudata(L, 5, LUAT_ZBUFF_TYPE);
  282. luat_color_t *color = (luat_color_t *)buff->addr;
  283. ret = luat_lcd_draw(default_conf, x1, y1, x2, y2, color);
  284. }
  285. else if(lua_isstring(L, 5)) {
  286. luat_color_t *color = (luat_color_t *)luaL_checkstring(L, 5);
  287. ret = luat_lcd_draw(default_conf, x1, y1, x2, y2, color);
  288. }
  289. else {
  290. return 0;
  291. }
  292. // int ret = luat_lcd_draw(default_conf, x1, y1, x2, y2, color);
  293. lua_pushboolean(L, ret == 0 ? 1 : 0);
  294. return 1;
  295. }
  296. /*
  297. lcd清屏
  298. @api lcd.clear(color)
  299. @int 屏幕颜色 可选参数,默认背景色
  300. @usage
  301. -- lcd清屏
  302. lcd.clear()
  303. */
  304. static int l_lcd_clear(lua_State* L) {
  305. //size_t len = 0;
  306. uint32_t color = BACK_COLOR;
  307. if (lua_gettop(L) > 0)
  308. color = (uint32_t)luaL_checkinteger(L, 1);
  309. int ret = luat_lcd_clear(default_conf, color);
  310. lua_pushboolean(L, ret == 0 ? 1 : 0);
  311. return 1;
  312. }
  313. /*
  314. lcd颜色填充
  315. @api lcd.fill(x1, y1, x2, y2,color)
  316. @int 左上边缘的X位置.
  317. @int 左上边缘的Y位置.
  318. @int 右上边缘的X位置.
  319. @int 右上边缘的Y位置.
  320. @int 绘画颜色 可选参数,默认背景色
  321. @usage
  322. -- lcd颜色填充
  323. lcd.fill(20,30,220,30,0x0000)
  324. */
  325. static int l_lcd_draw_fill(lua_State* L) {
  326. uint16_t x1, y1, x2, y2;
  327. uint32_t color = BACK_COLOR;
  328. x1 = luaL_checkinteger(L, 1);
  329. y1 = luaL_checkinteger(L, 2);
  330. x2 = luaL_checkinteger(L, 3);
  331. y2 = luaL_checkinteger(L, 4);
  332. if (lua_gettop(L) > 4)
  333. color = (uint32_t)luaL_checkinteger(L, 5);
  334. int ret = luat_lcd_draw_fill(default_conf, x1, y1, x2, y2, color);
  335. lua_pushboolean(L, ret == 0 ? 1 : 0);
  336. return 1;
  337. }
  338. /*
  339. 画一个点.
  340. @api lcd.drawPoint(x0,y0,color)
  341. @int 点的X位置.
  342. @int 点的Y位置.
  343. @int 绘画颜色 可选参数,默认前景色
  344. @usage
  345. lcd.drawPoint(20,30,0x001F)
  346. */
  347. static int l_lcd_draw_point(lua_State* L) {
  348. uint16_t x, y;
  349. uint32_t color = FORE_COLOR;
  350. x = luaL_checkinteger(L, 1);
  351. y = luaL_checkinteger(L, 2);
  352. if (lua_gettop(L) > 2)
  353. color = (uint32_t)luaL_checkinteger(L, 3);
  354. int ret = luat_lcd_draw_point(default_conf, x, y, color);
  355. lua_pushboolean(L, ret == 0 ? 1 : 0);
  356. return 1;
  357. }
  358. /*
  359. 在两点之间画一条线.
  360. @api lcd.drawLine(x0,y0,x1,y1,color)
  361. @int 第一个点的X位置.
  362. @int 第一个点的Y位置.
  363. @int 第二个点的X位置.
  364. @int 第二个点的Y位置.
  365. @int 绘画颜色 可选参数,默认前景色
  366. @usage
  367. lcd.drawLine(20,30,220,30,0x001F)
  368. */
  369. static int l_lcd_draw_line(lua_State* L) {
  370. uint16_t x1, y1, x2, y2;
  371. uint32_t color = FORE_COLOR;
  372. x1 = luaL_checkinteger(L, 1);
  373. y1 = luaL_checkinteger(L, 2);
  374. x2 = luaL_checkinteger(L, 3);
  375. y2 = luaL_checkinteger(L, 4);
  376. if (lua_gettop(L) > 4)
  377. color = (uint32_t)luaL_checkinteger(L, 5);
  378. int ret = luat_lcd_draw_line(default_conf, x1, y1, x2, y2, color);
  379. lua_pushboolean(L, ret == 0 ? 1 : 0);
  380. return 1;
  381. }
  382. /*
  383. 从x / y位置(左上边缘)开始绘制一个框
  384. @api lcd.drawRectangle(x0,y0,x1,y1,color)
  385. @int 左上边缘的X位置.
  386. @int 左上边缘的Y位置.
  387. @int 右下边缘的X位置.
  388. @int 右下边缘的Y位置.
  389. @int 绘画颜色 可选参数,默认前景色
  390. @usage
  391. lcd.drawRectangle(20,40,220,80,0x001F)
  392. */
  393. static int l_lcd_draw_rectangle(lua_State* L) {
  394. uint16_t x1, y1, x2, y2;
  395. uint32_t color = FORE_COLOR;
  396. x1 = luaL_checkinteger(L, 1);
  397. y1 = luaL_checkinteger(L, 2);
  398. x2 = luaL_checkinteger(L, 3);
  399. y2 = luaL_checkinteger(L, 4);
  400. if (lua_gettop(L) > 4)
  401. color = (uint32_t)luaL_checkinteger(L, 5);
  402. int ret = luat_lcd_draw_rectangle(default_conf, x1, y1, x2, y2, color);
  403. lua_pushboolean(L, ret == 0 ? 1 : 0);
  404. return 1;
  405. }
  406. /*
  407. 从x / y位置(圆心)开始绘制一个圆
  408. @api lcd.drawCircle(x0,y0,r,color)
  409. @int 圆心的X位置.
  410. @int 圆心的Y位置.
  411. @int 半径.
  412. @int 绘画颜色 可选参数,默认前景色
  413. @usage
  414. lcd.drawCircle(120,120,20,0x001F)
  415. */
  416. static int l_lcd_draw_circle(lua_State* L) {
  417. uint16_t x0, y0, r;
  418. uint32_t color = FORE_COLOR;
  419. x0 = luaL_checkinteger(L, 1);
  420. y0 = luaL_checkinteger(L, 2);
  421. r = luaL_checkinteger(L, 3);
  422. if (lua_gettop(L) > 3)
  423. color = (uint32_t)luaL_checkinteger(L, 4);
  424. int ret = luat_lcd_draw_circle(default_conf, x0, y0, r, color);
  425. lua_pushboolean(L, ret == 0 ? 1 : 0);
  426. return 1;
  427. }
  428. static uint8_t utf8_state;
  429. static uint16_t encoding;
  430. static uint16_t utf8_next(uint8_t b)
  431. {
  432. if ( b == 0 ) /* '\n' terminates the string to support the string list procedures */
  433. return 0x0ffff; /* end of string detected, pending UTF8 is discarded */
  434. if ( utf8_state == 0 )
  435. {
  436. if ( b >= 0xfc ) /* 6 byte sequence */
  437. {
  438. utf8_state = 5;
  439. b &= 1;
  440. }
  441. else if ( b >= 0xf8 )
  442. {
  443. utf8_state = 4;
  444. b &= 3;
  445. }
  446. else if ( b >= 0xf0 )
  447. {
  448. utf8_state = 3;
  449. b &= 7;
  450. }
  451. else if ( b >= 0xe0 )
  452. {
  453. utf8_state = 2;
  454. b &= 15;
  455. }
  456. else if ( b >= 0xc0 )
  457. {
  458. utf8_state = 1;
  459. b &= 0x01f;
  460. }
  461. else
  462. {
  463. /* do nothing, just use the value as encoding */
  464. return b;
  465. }
  466. encoding = b;
  467. return 0x0fffe;
  468. }
  469. else
  470. {
  471. utf8_state--;
  472. /* The case b < 0x080 (an illegal UTF8 encoding) is not checked here. */
  473. encoding<<=6;
  474. b &= 0x03f;
  475. encoding |= b;
  476. if ( utf8_state != 0 )
  477. return 0x0fffe; /* nothing to do yet */
  478. }
  479. return encoding;
  480. }
  481. static void u8g2_draw_hv_line(u8g2_t *u8g2, int16_t x, int16_t y, int16_t len, uint8_t dir, uint16_t color){
  482. switch(dir)
  483. {
  484. case 0:
  485. luat_lcd_draw_hline(default_conf,x,y,len,color);
  486. break;
  487. case 1:
  488. luat_lcd_draw_vline(default_conf,x,y,len,color);
  489. break;
  490. case 2:
  491. luat_lcd_draw_hline(default_conf,x-len+1,y,len,color);
  492. break;
  493. case 3:
  494. luat_lcd_draw_vline(default_conf,x,y-len+1,len,color);
  495. break;
  496. }
  497. }
  498. static int16_t u8g2_add_vector_x(int16_t dx, int8_t x, int8_t y, uint8_t dir) U8X8_NOINLINE;
  499. static int16_t u8g2_add_vector_x(int16_t dx, int8_t x, int8_t y, uint8_t dir)
  500. {
  501. switch(dir)
  502. {
  503. case 0:
  504. dx += x;
  505. break;
  506. case 1:
  507. dx -= y;
  508. break;
  509. case 2:
  510. dx -= x;
  511. break;
  512. default:
  513. dx += y;
  514. break;
  515. }
  516. return dx;
  517. }
  518. static int16_t u8g2_add_vector_y(int16_t dy, int8_t x, int8_t y, uint8_t dir) U8X8_NOINLINE;
  519. static int16_t u8g2_add_vector_y(int16_t dy, int8_t x, int8_t y, uint8_t dir)
  520. {
  521. switch(dir)
  522. {
  523. case 0:
  524. dy += y;
  525. break;
  526. case 1:
  527. dy += x;
  528. break;
  529. case 2:
  530. dy -= y;
  531. break;
  532. default:
  533. dy -= x;
  534. break;
  535. }
  536. return dy;
  537. }
  538. static void u8g2_font_decode_len(u8g2_t *u8g2, uint8_t len, uint8_t is_foreground){
  539. uint8_t cnt; /* total number of remaining pixels, which have to be drawn */
  540. uint8_t rem; /* remaining pixel to the right edge of the glyph */
  541. uint8_t current; /* number of pixels, which need to be drawn for the draw procedure */
  542. /* current is either equal to cnt or equal to rem */
  543. /* local coordinates of the glyph */
  544. uint8_t lx,ly;
  545. /* target position on the screen */
  546. int16_t x, y;
  547. u8g2_font_decode_t *decode = &(u8g2->font_decode);
  548. cnt = len;
  549. /* get the local position */
  550. lx = decode->x;
  551. ly = decode->y;
  552. for(;;){
  553. /* calculate the number of pixel to the right edge of the glyph */
  554. rem = decode->glyph_width;
  555. rem -= lx;
  556. /* calculate how many pixel to draw. This is either to the right edge */
  557. /* or lesser, if not enough pixel are left */
  558. current = rem;
  559. if ( cnt < rem )
  560. current = cnt;
  561. /* now draw the line, but apply the rotation around the glyph target position */
  562. //u8g2_font_decode_draw_pixel(u8g2, lx,ly,current, is_foreground);
  563. /* get target position */
  564. x = decode->target_x;
  565. y = decode->target_y;
  566. /* apply rotation */
  567. x = u8g2_add_vector_x(x, lx, ly, decode->dir);
  568. y = u8g2_add_vector_y(y, lx, ly, decode->dir);
  569. /* draw foreground and background (if required) */
  570. if ( current > 0 ) /* avoid drawing zero length lines, issue #4 */
  571. {
  572. if ( is_foreground )
  573. {
  574. u8g2_draw_hv_line(u8g2, x, y, current, decode->dir, lcd_str_fg_color);
  575. }
  576. else if ( decode->is_transparent == 0 )
  577. {
  578. u8g2_draw_hv_line(u8g2, x, y, current, decode->dir, lcd_str_bg_color);
  579. }
  580. }
  581. /* check, whether the end of the run length code has been reached */
  582. if ( cnt < rem )
  583. break;
  584. cnt -= rem;
  585. lx = 0;
  586. ly++;
  587. }
  588. lx += cnt;
  589. decode->x = lx;
  590. decode->y = ly;
  591. }
  592. static void u8g2_font_setup_decode(u8g2_t *u8g2, const uint8_t *glyph_data)
  593. {
  594. u8g2_font_decode_t *decode = &(u8g2->font_decode);
  595. decode->decode_ptr = glyph_data;
  596. decode->decode_bit_pos = 0;
  597. /* 8 Nov 2015, this is already done in the glyph data search procedure */
  598. /*
  599. decode->decode_ptr += 1;
  600. decode->decode_ptr += 1;
  601. */
  602. decode->glyph_width = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_char_width);
  603. decode->glyph_height = u8g2_font_decode_get_unsigned_bits(decode,u8g2->font_info.bits_per_char_height);
  604. }
  605. static int8_t u8g2_font_decode_glyph(u8g2_t *u8g2, const uint8_t *glyph_data){
  606. uint8_t a, b;
  607. int8_t x, y;
  608. int8_t d;
  609. int8_t h;
  610. u8g2_font_decode_t *decode = &(u8g2->font_decode);
  611. u8g2_font_setup_decode(u8g2, glyph_data);
  612. h = u8g2->font_decode.glyph_height;
  613. x = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_x);
  614. y = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_y);
  615. d = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_delta_x);
  616. if ( decode->glyph_width > 0 )
  617. {
  618. decode->target_x = u8g2_add_vector_x(decode->target_x, x, -(h+y), decode->dir);
  619. decode->target_y = u8g2_add_vector_y(decode->target_y, x, -(h+y), decode->dir);
  620. //u8g2_add_vector(&(decode->target_x), &(decode->target_y), x, -(h+y), decode->dir);
  621. /* reset local x/y position */
  622. decode->x = 0;
  623. decode->y = 0;
  624. /* decode glyph */
  625. for(;;){
  626. a = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_0);
  627. b = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_1);
  628. do{
  629. u8g2_font_decode_len(u8g2, a, 0);
  630. u8g2_font_decode_len(u8g2, b, 1);
  631. } while( u8g2_font_decode_get_unsigned_bits(decode, 1) != 0 );
  632. if ( decode->y >= h )
  633. break;
  634. }
  635. }
  636. return d;
  637. }
  638. const uint8_t *u8g2_font_get_glyph_data(u8g2_t *u8g2, uint16_t encoding);
  639. static int16_t u8g2_font_draw_glyph(u8g2_t *u8g2, int16_t x, int16_t y, uint16_t encoding){
  640. int16_t dx = 0;
  641. u8g2->font_decode.target_x = x;
  642. u8g2->font_decode.target_y = y;
  643. const uint8_t *glyph_data = u8g2_font_get_glyph_data(u8g2, encoding);
  644. if ( glyph_data != NULL ){
  645. dx = u8g2_font_decode_glyph(u8g2, glyph_data);
  646. }
  647. return dx;
  648. }
  649. /*
  650. 设置字体
  651. @api lcd.setFont(font)
  652. @string font
  653. @usage
  654. -- 设置为中文字体,对之后的drawStr有效,使用中文字体需在luat_conf_bsp.h.h开启#define USE_U8G2_OPPOSANSM12_CHINESE
  655. lcd.setFont(lcd.font_opposansm12)
  656. lcd.drawStr(40,10,"drawStr")
  657. sys.wait(2000)
  658. lcd.setFont(lcd.font_opposansm12_chinese)
  659. lcd.drawStr(40,40,"drawStr测试")
  660. */
  661. static int l_lcd_set_font(lua_State *L) {
  662. int font = luaL_checkinteger(L, 1);
  663. switch (font)
  664. {
  665. case font_opposansm8:
  666. LLOGI("font_opposansm8");
  667. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), u8g2_font_opposansm8);
  668. lua_pushboolean(L, 1);
  669. break;
  670. case font_opposansm10:
  671. LLOGI("font_opposansm10");
  672. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), u8g2_font_opposansm10);
  673. lua_pushboolean(L, 1);
  674. break;
  675. case font_opposansm12:
  676. LLOGI("font_opposansm12");
  677. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), u8g2_font_opposansm12);
  678. lua_pushboolean(L, 1);
  679. break;
  680. case font_opposansm16:
  681. LLOGI("font_opposansm16");
  682. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), u8g2_font_opposansm16);
  683. lua_pushboolean(L, 1);
  684. break;
  685. case font_opposansm18:
  686. LLOGI("font_opposansm18");
  687. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), u8g2_font_opposansm18);
  688. lua_pushboolean(L, 1);
  689. break;
  690. case font_opposansm20:
  691. LLOGI("font_opposansm20");
  692. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), u8g2_font_opposansm20);
  693. lua_pushboolean(L, 1);
  694. break;
  695. case font_opposansm22:
  696. LLOGI("font_opposansm22");
  697. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), u8g2_font_opposansm22);
  698. lua_pushboolean(L, 1);
  699. break;
  700. case font_opposansm24:
  701. LLOGI("font_opposansm24");
  702. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), u8g2_font_opposansm24);
  703. lua_pushboolean(L, 1);
  704. break;
  705. case font_opposansm32:
  706. LLOGI("font_opposansm32");
  707. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), u8g2_font_opposansm32);
  708. lua_pushboolean(L, 1);
  709. break;
  710. #if defined USE_U8G2_OPPOSANSM12_CHINESE
  711. case font_opposansm12_chinese:
  712. LLOGI("font_opposansm12_chinese");
  713. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), u8g2_font_opposansm12_chinese);
  714. lua_pushboolean(L, 1);
  715. break;
  716. #endif
  717. #if defined USE_U8G2_OPPOSANSM16_CHINESE
  718. case font_opposansm16_chinese:
  719. LLOGI("font_opposansm16_chinese");
  720. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), u8g2_font_opposansm16_chinese);
  721. lua_pushboolean(L, 1);
  722. break;
  723. #endif
  724. #if defined USE_U8G2_OPPOSANSM24_CHINESE
  725. case font_opposansm24_chinese:
  726. LLOGI("font_opposansm24_chinese");
  727. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), u8g2_font_opposansm24_chinese);
  728. lua_pushboolean(L, 1);
  729. break;
  730. #endif
  731. #if defined USE_U8G2_OPPOSANSM32_CHINESE
  732. case font_opposansm32_chinese:
  733. LLOGI("font_opposansm32_chinese");
  734. u8g2_SetFont(&(default_conf->luat_lcd_u8g2), u8g2_font_opposansm32_chinese);
  735. lua_pushboolean(L, 1);
  736. break;
  737. #endif
  738. default:
  739. lua_pushboolean(L, 0);
  740. LLOGI("no font");
  741. break;
  742. }
  743. return 1;
  744. }
  745. /*
  746. 显示字符串
  747. @api lcd.drawStr(x,y,str,fg_color,bg_color)
  748. @int x 横坐标
  749. @int y 竖坐标
  750. @string str 文件内容
  751. @int fg_color str颜色
  752. @int bg_color str背景颜色
  753. @usage
  754. -- 显示之前先设置为中文字体,对之后的drawStr有效,使用中文字体需在luat_conf_bsp.h.h开启#define USE_U8G2_WQY16_T_GB2312
  755. lcd.setFont(lcd.font_opposansm12)
  756. lcd.drawStr(40,10,"drawStr")
  757. sys.wait(2000)
  758. lcd.setFont(lcd.font_opposansm16_chinese)
  759. lcd.drawStr(40,40,"drawStr测试")
  760. */
  761. static int l_lcd_draw_str(lua_State* L) {
  762. int x, y;
  763. int sz;
  764. const uint8_t* data;
  765. uint32_t color = FORE_COLOR;
  766. x = luaL_checkinteger(L, 1);
  767. y = luaL_checkinteger(L, 2);
  768. data = (const uint8_t*)luaL_checklstring(L, 3, &sz);
  769. lcd_str_fg_color = (uint32_t)luaL_optinteger(L, 4,FORE_COLOR);
  770. lcd_str_bg_color = (uint32_t)luaL_optinteger(L, 5,BACK_COLOR);
  771. if (sz == 0)
  772. return 0;
  773. uint16_t e;
  774. int16_t delta, sum;
  775. utf8_state = 0;
  776. sum = 0;
  777. for(;;){
  778. e = utf8_next((uint8_t)*data);
  779. if ( e == 0x0ffff )
  780. break;
  781. data++;
  782. if ( e != 0x0fffe ){
  783. delta = u8g2_font_draw_glyph(&(default_conf->luat_lcd_u8g2), x, y, e);
  784. switch(default_conf->luat_lcd_u8g2.font_decode.dir){
  785. case 0:
  786. x += delta;
  787. break;
  788. case 1:
  789. y += delta;
  790. break;
  791. case 2:
  792. x -= delta;
  793. break;
  794. case 3:
  795. y -= delta;
  796. break;
  797. }
  798. sum += delta;
  799. }
  800. }
  801. return 0;
  802. }
  803. #ifdef LUAT_USE_GTFONT
  804. #include "GT5SLCD2E_1A.h"
  805. 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);
  806. 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);
  807. static int l_lcd_draw_gtfont_gb2312(lua_State *L) {
  808. unsigned char buf[128];
  809. int len;
  810. int i = 0;
  811. uint8_t strhigh,strlow ;
  812. uint16_t str;
  813. const char *fontCode = luaL_checklstring(L, 1,&len);
  814. unsigned char size = luaL_checkinteger(L, 2);
  815. int x = luaL_checkinteger(L, 3);
  816. int y = luaL_checkinteger(L, 4);
  817. while ( i < len){
  818. strhigh = *fontCode;
  819. fontCode++;
  820. strlow = *fontCode;
  821. str = (strhigh<<8)|strlow;
  822. fontCode++;
  823. get_font(buf, 1, str, size, size, size);
  824. gtfont_draw_w(buf , x ,y , size , size,luat_lcd_draw_point,default_conf,0);
  825. x+=size;
  826. i+=2;
  827. }
  828. return 0;
  829. }
  830. static int l_lcd_draw_gtfont_gb2312_gray(lua_State* L) {
  831. unsigned char buf[2048];
  832. int len;
  833. int i = 0;
  834. uint8_t strhigh,strlow ;
  835. uint16_t str;
  836. const char *fontCode = luaL_checklstring(L, 1,&len);
  837. unsigned char size = luaL_checkinteger(L, 2);
  838. unsigned char font_g = luaL_checkinteger(L, 3);
  839. int x = luaL_checkinteger(L, 4);
  840. int y = luaL_checkinteger(L, 5);
  841. while ( i < len){
  842. strhigh = *fontCode;
  843. fontCode++;
  844. strlow = *fontCode;
  845. str = (strhigh<<8)|strlow;
  846. fontCode++;
  847. get_font(buf, 1, str, size*font_g, size*font_g, size*font_g);
  848. Gray_Process(buf,size,size,font_g);
  849. gtfont_draw_gray_hz(buf, x, y, size , size, font_g, 1,luat_lcd_draw_point,default_conf,0);
  850. x+=size;
  851. i+=2;
  852. }
  853. return 0;
  854. }
  855. #ifdef LUAT_USE_GTFONT_UTF8
  856. extern unsigned short unicodetogb2312 ( unsigned short chr);
  857. static int l_lcd_draw_gtfont_utf8(lua_State *L) {
  858. unsigned char buf[128];
  859. int len;
  860. int i = 0;
  861. uint8_t strhigh,strlow ;
  862. uint16_t e,str;
  863. const char *fontCode = luaL_checklstring(L, 1,&len);
  864. unsigned char size = luaL_checkinteger(L, 2);
  865. int x = luaL_checkinteger(L, 3);
  866. int y = luaL_checkinteger(L, 4);
  867. for(;;){
  868. e = utf8_next((uint8_t)*fontCode);
  869. if ( e == 0x0ffff )
  870. break;
  871. fontCode++;
  872. if ( e != 0x0fffe ){
  873. uint16_t str = unicodetogb2312(e);
  874. get_font(buf, 1, str, size, size, size);
  875. gtfont_draw_w(buf , x ,y , size , size,luat_lcd_draw_point,default_conf,0);
  876. x+=size;
  877. }
  878. }
  879. return 0;
  880. }
  881. static int l_lcd_draw_gtfont_utf8_gray(lua_State* L) {
  882. unsigned char buf[2048];
  883. int len;
  884. int i = 0;
  885. uint8_t strhigh,strlow ;
  886. uint16_t e,str;
  887. const char *fontCode = luaL_checklstring(L, 1,&len);
  888. unsigned char size = luaL_checkinteger(L, 2);
  889. unsigned char font_g = luaL_checkinteger(L, 3);
  890. int x = luaL_checkinteger(L, 4);
  891. int y = luaL_checkinteger(L, 5);
  892. for(;;){
  893. e = utf8_next((uint8_t)*fontCode);
  894. if ( e == 0x0ffff )
  895. break;
  896. fontCode++;
  897. if ( e != 0x0fffe ){
  898. uint16_t str = unicodetogb2312(e);
  899. get_font(buf, 1, str, size*font_g, size*font_g, size*font_g);
  900. Gray_Process(buf,size,size,font_g);
  901. gtfont_draw_gray_hz(buf, x, y, size , size, font_g, 1,luat_lcd_draw_point,default_conf,0);
  902. x+=size;
  903. }
  904. }
  905. return 0;
  906. }
  907. #endif // LUAT_USE_GTFONT_UTF8
  908. #endif // LUAT_USE_GTFONT
  909. static int l_lcd_set_default(lua_State *L) {
  910. if (lua_gettop(L) == 1) {
  911. default_conf = lua_touserdata(L, 1);
  912. lua_pushboolean(L, 1);
  913. return 1;
  914. }
  915. return 1;
  916. }
  917. #include "rotable.h"
  918. static const rotable_Reg reg_lcd[] =
  919. {
  920. { "init", l_lcd_init, 0},
  921. { "close", l_lcd_close, 0},
  922. { "on", l_lcd_display_on, 0},
  923. { "off", l_lcd_display_off, 0},
  924. { "sleep", l_lcd_sleep, 0},
  925. { "wakeup", l_lcd_wakeup, 0},
  926. { "setColor", l_lcd_set_color, 0},
  927. { "draw", l_lcd_draw, 0},
  928. { "clear", l_lcd_clear, 0},
  929. { "fill", l_lcd_draw_fill, 0},
  930. { "drawPoint", l_lcd_draw_point, 0},
  931. { "drawLine", l_lcd_draw_line, 0},
  932. { "drawRectangle", l_lcd_draw_rectangle, 0},
  933. { "drawCircle", l_lcd_draw_circle, 0},
  934. { "drawStr", l_lcd_draw_str, 0},
  935. { "setFont", l_lcd_set_font, 0},
  936. { "setDefault", l_lcd_set_default, 0},
  937. #ifdef LUAT_USE_GTFONT
  938. { "drawGtfontGb2312", l_lcd_draw_gtfont_gb2312, 0},
  939. { "drawGtfontGb2312Gray", l_lcd_draw_gtfont_gb2312_gray, 0},
  940. #ifdef LUAT_USE_GTFONT_UTF8
  941. { "drawGtfontUtf8", l_lcd_draw_gtfont_utf8, 0},
  942. { "drawGtfontUtf8Gray", l_lcd_draw_gtfont_utf8_gray, 0},
  943. #endif // LUAT_USE_GTFONT_UTF8
  944. #endif // LUAT_USE_GTFONT
  945. { "font_opposansm8", NULL, font_opposansm8},
  946. { "font_opposansm10", NULL, font_opposansm10},
  947. { "font_opposansm12", NULL, font_opposansm12},
  948. { "font_opposansm16", NULL, font_opposansm16},
  949. { "font_opposansm18", NULL, font_opposansm18},
  950. { "font_opposansm20", NULL, font_opposansm20},
  951. { "font_opposansm22", NULL, font_opposansm22},
  952. { "font_opposansm24", NULL, font_opposansm24},
  953. { "font_opposansm32", NULL, font_opposansm32},
  954. { "font_opposansm12_chinese", NULL, font_opposansm12_chinese},
  955. { "font_opposansm16_chinese", NULL, font_opposansm16_chinese},
  956. { "font_opposansm24_chinese", NULL, font_opposansm24_chinese},
  957. { "font_opposansm32_chinese", NULL, font_opposansm32_chinese},
  958. { NULL, NULL, 0}
  959. };
  960. LUAMOD_API int luaopen_lcd( lua_State *L ) {
  961. luat_newlib(L, reg_lcd);
  962. return 1;
  963. }