luat_lib_lcd.c 69 KB

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