luat_lib_eink.c 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  1. /*
  2. @module eink
  3. @summary 墨水屏操作库
  4. @version 1.0
  5. @date 2020.11.14
  6. */
  7. #include "luat_base.h"
  8. #include "luat_log.h"
  9. #include "luat_sys.h"
  10. #include "luat_msgbus.h"
  11. #include "luat_timer.h"
  12. #include "luat_malloc.h"
  13. #include "luat_spi.h"
  14. #include "luat_gpio.h"
  15. // #include "epd1in54.h"
  16. // #include "epd2in9.h"
  17. #include "epd.h"
  18. #include "epdpaint.h"
  19. #include "imagedata.h"
  20. #include "../qrcode/qrcode.h"
  21. #include <stdlib.h>
  22. #include "u8g2.h"
  23. int8_t u8g2_font_decode_get_signed_bits(u8g2_font_decode_t *f, uint8_t cnt);
  24. uint8_t u8g2_font_decode_get_unsigned_bits(u8g2_font_decode_t *f, uint8_t cnt);
  25. #define COLORED 0
  26. #define UNCOLORED 1
  27. #define LUAT_LOG_TAG "luat.eink"
  28. enum
  29. {
  30. font_opposansm8,
  31. font_opposansm10,
  32. font_opposansm12,
  33. font_opposansm16,
  34. font_opposansm18,
  35. font_opposansm20,
  36. font_opposansm22,
  37. font_opposansm24,
  38. font_opposansm32,
  39. font_opposansm12_chinese,
  40. font_opposansm16_chinese,
  41. font_opposansm24_chinese,
  42. font_opposansm32_chinese,
  43. };
  44. static uint32_t eink_str_color;
  45. // static EPD epd;
  46. static Paint paint;
  47. static unsigned char* frame_buffer = NULL;
  48. // #ifdef econf
  49. // #undef econf
  50. // #endif
  51. eink_conf_t econf = {0};
  52. #define Pin_BUSY (econf.busy_pin)
  53. #define Pin_RES (econf.res_pin)
  54. #define Pin_DC (econf.dc_pin)
  55. #define Pin_CS (econf.cs_pin)
  56. #define SPI_ID (econf.spi_id)
  57. /**
  58. 初始化eink
  59. @api eink.setup(full, spiid)
  60. @int 全屏刷新0,局部刷新1,默认是全屏刷新
  61. @int 所在的spi,默认是0
  62. @return boolean 成功返回true,否则返回false
  63. */
  64. static int l_eink_setup(lua_State *L) {
  65. int status;
  66. econf.full_mode = luaL_optinteger(L, 1, 1);
  67. econf.spi_id = luaL_optinteger(L, 2, 0);
  68. econf.busy_pin = luaL_optinteger(L, 3, 18);
  69. econf.res_pin = luaL_optinteger(L, 4, 7);
  70. econf.dc_pin = luaL_optinteger(L, 5, 9);
  71. econf.cs_pin = luaL_optinteger(L, 6, 16);
  72. if (frame_buffer != NULL) {
  73. lua_pushboolean(L, 1);
  74. return 0;
  75. }
  76. if (lua_type(L, 7) == LUA_TUSERDATA){
  77. LLOGD("luat_spi_device_send");
  78. econf.userdata = (luat_spi_device_t*)lua_touserdata(L, 3);
  79. econf.port = LUAT_EINK_SPI_DEVICE;
  80. luat_gpio_mode(Pin_BUSY, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
  81. luat_gpio_mode(Pin_RES, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
  82. luat_gpio_mode(Pin_DC, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
  83. status = 0;
  84. }else{
  85. LLOGD("luat_spi_send");
  86. luat_spi_t spi_config = {0};
  87. spi_config.bandrate = 2000000U;//luaL_optinteger(L, 1, 2000000U); // 2000000U
  88. spi_config.id = SPI_ID;
  89. spi_config.cs = 255; // 默认无
  90. spi_config.CPHA = 0; // CPHA0
  91. spi_config.CPOL = 0; // CPOL0
  92. spi_config.dataw = 8; // 8bit
  93. spi_config.bit_dict = 1; // MSB=1, LSB=0
  94. spi_config.master = 1; // master=1,slave=0
  95. spi_config.mode = 1; // FULL=1, half=0
  96. //LLOGD("setup GPIO for epd");
  97. luat_gpio_mode(Pin_BUSY, Luat_GPIO_INPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
  98. luat_gpio_mode(Pin_RES, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
  99. luat_gpio_mode(Pin_DC, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
  100. luat_gpio_mode(Pin_CS, Luat_GPIO_OUTPUT, Luat_GPIO_PULLUP, Luat_GPIO_LOW);
  101. status = luat_spi_setup(&spi_config);
  102. }
  103. size_t epd_w = 0;
  104. size_t epd_h = 0;
  105. if(status == 0)
  106. {
  107. LLOGD("spi setup complete, now setup epd");
  108. if(econf.full_mode)
  109. status = EPD_Init(1, &epd_w, &epd_h);
  110. else
  111. status = EPD_Init(0, &epd_w, &epd_h);
  112. if (status != 0) {
  113. LLOGD("e-Paper init failed");
  114. return 0;
  115. }
  116. frame_buffer = (unsigned char*)luat_heap_malloc(epd_w * epd_h / 8);
  117. // Paint paint;
  118. Paint_Init(&paint, frame_buffer, epd_w, epd_h);
  119. Paint_Clear(&paint, UNCOLORED);
  120. }
  121. u8g2_SetFontMode(&(paint.luat_eink_u8g2), 0);
  122. u8g2_SetFontDirection(&(paint.luat_eink_u8g2), 0);
  123. //LLOGD("epd init complete");
  124. lua_pushboolean(L, 1);
  125. return 1;
  126. }
  127. /**
  128. 清除绘图缓冲区
  129. @api eink.clear()
  130. @return nil 无返回值,不会马上刷新到设备
  131. */
  132. static int l_eink_clear(lua_State *L)
  133. {
  134. int colored = luaL_optinteger(L, 1, 1);
  135. Paint_Clear(&paint, colored);
  136. return 0;
  137. }
  138. /**
  139. 设置窗口
  140. @api eink.setWin(width, height, rotate)
  141. @int width 宽度
  142. @int height 高度
  143. @int rotate 显示方向,0/1/2/3, 相当于旋转0度/90度/180度/270度
  144. @return nil 无返回值
  145. */
  146. static int l_eink_setWin(lua_State *L)
  147. {
  148. int width = luaL_checkinteger(L, 1);
  149. int height = luaL_checkinteger(L, 2);
  150. int rotate = luaL_checkinteger(L, 3);
  151. Paint_SetWidth(&paint, width);
  152. Paint_SetHeight(&paint, height);
  153. Paint_SetRotate(&paint, rotate);
  154. return 0;
  155. }
  156. /**
  157. 获取窗口信息
  158. @api eink.getWin()
  159. @return int width 宽
  160. @return int height 高
  161. @return int rotate 旋转方向
  162. */
  163. static int l_eink_getWin(lua_State *L)
  164. {
  165. int width = Paint_GetWidth(&paint);
  166. int height = Paint_GetHeight(&paint);
  167. int rotate = Paint_GetRotate(&paint);
  168. lua_pushinteger(L, width);
  169. lua_pushinteger(L, height);
  170. lua_pushinteger(L, rotate);
  171. return 3;
  172. }
  173. static uint8_t utf8_state;
  174. static uint16_t encoding;
  175. static uint16_t utf8_next(uint8_t b)
  176. {
  177. if ( b == 0 ) /* '\n' terminates the string to support the string list procedures */
  178. return 0x0ffff; /* end of string detected, pending UTF8 is discarded */
  179. if ( utf8_state == 0 )
  180. {
  181. if ( b >= 0xfc ) /* 6 byte sequence */
  182. {
  183. utf8_state = 5;
  184. b &= 1;
  185. }
  186. else if ( b >= 0xf8 )
  187. {
  188. utf8_state = 4;
  189. b &= 3;
  190. }
  191. else if ( b >= 0xf0 )
  192. {
  193. utf8_state = 3;
  194. b &= 7;
  195. }
  196. else if ( b >= 0xe0 )
  197. {
  198. utf8_state = 2;
  199. b &= 15;
  200. }
  201. else if ( b >= 0xc0 )
  202. {
  203. utf8_state = 1;
  204. b &= 0x01f;
  205. }
  206. else
  207. {
  208. /* do nothing, just use the value as encoding */
  209. return b;
  210. }
  211. encoding = b;
  212. return 0x0fffe;
  213. }
  214. else
  215. {
  216. utf8_state--;
  217. /* The case b < 0x080 (an illegal UTF8 encoding) is not checked here. */
  218. encoding<<=6;
  219. b &= 0x03f;
  220. encoding |= b;
  221. if ( utf8_state != 0 )
  222. return 0x0fffe; /* nothing to do yet */
  223. }
  224. return encoding;
  225. }
  226. static void drawFastHLine(Paint* conf,int16_t x, int16_t y, int16_t len, uint16_t color){
  227. Paint_DrawHorizontalLine(conf,x, y, len,color);
  228. }
  229. static void drawFastVLine(Paint* conf,int16_t x, int16_t y, int16_t len, uint16_t color){
  230. Paint_DrawVerticalLine(conf,x, y, len,color);
  231. }
  232. static void u8g2_draw_hv_line(u8g2_t *u8g2, int16_t x, int16_t y, int16_t len, uint8_t dir, uint16_t color){
  233. switch(dir)
  234. {
  235. case 0:
  236. drawFastHLine(&paint,x,y,len,color);
  237. break;
  238. case 1:
  239. drawFastVLine(&paint,x,y,len,color);
  240. break;
  241. case 2:
  242. drawFastHLine(&paint,x-len+1,y,len,color);
  243. break;
  244. case 3:
  245. drawFastVLine(&paint,x,y-len+1,len,color);
  246. break;
  247. }
  248. }
  249. static int16_t u8g2_add_vector_x(int16_t dx, int8_t x, int8_t y, uint8_t dir) U8X8_NOINLINE;
  250. static int16_t u8g2_add_vector_x(int16_t dx, int8_t x, int8_t y, uint8_t dir)
  251. {
  252. switch(dir)
  253. {
  254. case 0:
  255. dx += x;
  256. break;
  257. case 1:
  258. dx -= y;
  259. break;
  260. case 2:
  261. dx -= x;
  262. break;
  263. default:
  264. dx += y;
  265. break;
  266. }
  267. return dx;
  268. }
  269. static int16_t u8g2_add_vector_y(int16_t dy, int8_t x, int8_t y, uint8_t dir) U8X8_NOINLINE;
  270. static int16_t u8g2_add_vector_y(int16_t dy, int8_t x, int8_t y, uint8_t dir)
  271. {
  272. switch(dir)
  273. {
  274. case 0:
  275. dy += y;
  276. break;
  277. case 1:
  278. dy += x;
  279. break;
  280. case 2:
  281. dy -= y;
  282. break;
  283. default:
  284. dy -= x;
  285. break;
  286. }
  287. return dy;
  288. }
  289. static void u8g2_font_decode_len(u8g2_t *u8g2, uint8_t len, uint8_t is_foreground){
  290. uint8_t cnt; /* total number of remaining pixels, which have to be drawn */
  291. uint8_t rem; /* remaining pixel to the right edge of the glyph */
  292. uint8_t current; /* number of pixels, which need to be drawn for the draw procedure */
  293. /* current is either equal to cnt or equal to rem */
  294. /* local coordinates of the glyph */
  295. uint8_t lx,ly;
  296. /* target position on the screen */
  297. int16_t x, y;
  298. u8g2_font_decode_t *decode = &(u8g2->font_decode);
  299. cnt = len;
  300. /* get the local position */
  301. lx = decode->x;
  302. ly = decode->y;
  303. for(;;){
  304. /* calculate the number of pixel to the right edge of the glyph */
  305. rem = decode->glyph_width;
  306. rem -= lx;
  307. /* calculate how many pixel to draw. This is either to the right edge */
  308. /* or lesser, if not enough pixel are left */
  309. current = rem;
  310. if ( cnt < rem )
  311. current = cnt;
  312. /* now draw the line, but apply the rotation around the glyph target position */
  313. //u8g2_font_decode_draw_pixel(u8g2, lx,ly,current, is_foreground);
  314. /* get target position */
  315. x = decode->target_x;
  316. y = decode->target_y;
  317. /* apply rotation */
  318. x = u8g2_add_vector_x(x, lx, ly, decode->dir);
  319. y = u8g2_add_vector_y(y, lx, ly, decode->dir);
  320. /* draw foreground and background (if required) */
  321. if ( current > 0 ) /* avoid drawing zero length lines, issue #4 */
  322. {
  323. if ( is_foreground )
  324. {
  325. u8g2_draw_hv_line(u8g2, x, y, current, decode->dir, eink_str_color);
  326. }
  327. else if ( decode->is_transparent == 0 )
  328. {
  329. // u8g2_draw_hv_line(u8g2, x, y, current, decode->dir, decode->bg_color);
  330. }
  331. }
  332. /* check, whether the end of the run length code has been reached */
  333. if ( cnt < rem )
  334. break;
  335. cnt -= rem;
  336. lx = 0;
  337. ly++;
  338. }
  339. lx += cnt;
  340. decode->x = lx;
  341. decode->y = ly;
  342. }
  343. static void u8g2_font_setup_decode(u8g2_t *u8g2, const uint8_t *glyph_data)
  344. {
  345. u8g2_font_decode_t *decode = &(u8g2->font_decode);
  346. decode->decode_ptr = glyph_data;
  347. decode->decode_bit_pos = 0;
  348. /* 8 Nov 2015, this is already done in the glyph data search procedure */
  349. /*
  350. decode->decode_ptr += 1;
  351. decode->decode_ptr += 1;
  352. */
  353. decode->glyph_width = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_char_width);
  354. decode->glyph_height = u8g2_font_decode_get_unsigned_bits(decode,u8g2->font_info.bits_per_char_height);
  355. }
  356. static int8_t u8g2_font_decode_glyph(u8g2_t *u8g2, const uint8_t *glyph_data){
  357. uint8_t a, b;
  358. int8_t x, y;
  359. int8_t d;
  360. int8_t h;
  361. u8g2_font_decode_t *decode = &(u8g2->font_decode);
  362. u8g2_font_setup_decode(u8g2, glyph_data);
  363. h = u8g2->font_decode.glyph_height;
  364. x = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_x);
  365. y = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_char_y);
  366. d = u8g2_font_decode_get_signed_bits(decode, u8g2->font_info.bits_per_delta_x);
  367. if ( decode->glyph_width > 0 )
  368. {
  369. decode->target_x = u8g2_add_vector_x(decode->target_x, x, -(h+y), decode->dir);
  370. decode->target_y = u8g2_add_vector_y(decode->target_y, x, -(h+y), decode->dir);
  371. //u8g2_add_vector(&(decode->target_x), &(decode->target_y), x, -(h+y), decode->dir);
  372. /* reset local x/y position */
  373. decode->x = 0;
  374. decode->y = 0;
  375. /* decode glyph */
  376. for(;;){
  377. a = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_0);
  378. b = u8g2_font_decode_get_unsigned_bits(decode, u8g2->font_info.bits_per_1);
  379. do{
  380. u8g2_font_decode_len(u8g2, a, 0);
  381. u8g2_font_decode_len(u8g2, b, 1);
  382. } while( u8g2_font_decode_get_unsigned_bits(decode, 1) != 0 );
  383. if ( decode->y >= h )
  384. break;
  385. }
  386. }
  387. return d;
  388. }
  389. const uint8_t *u8g2_font_get_glyph_data(u8g2_t *u8g2, uint16_t encoding);
  390. static int16_t u8g2_font_draw_glyph(u8g2_t *u8g2, int16_t x, int16_t y, uint16_t encoding){
  391. int16_t dx = 0;
  392. u8g2->font_decode.target_x = x;
  393. u8g2->font_decode.target_y = y;
  394. const uint8_t *glyph_data = u8g2_font_get_glyph_data(u8g2, encoding);
  395. if ( glyph_data != NULL ){
  396. dx = u8g2_font_decode_glyph(u8g2, glyph_data);
  397. }
  398. return dx;
  399. }
  400. /**
  401. 绘制字符串
  402. @api eink.print(x, y, str, colored, font)
  403. @int x坐标
  404. @int y坐标
  405. @string 字符串
  406. @int 默认是0
  407. @font 字体大小,默认12
  408. @return nil 无返回值
  409. */
  410. static int l_eink_print(lua_State *L)
  411. {
  412. size_t len;
  413. int x = luaL_checkinteger(L, 1);
  414. int y = luaL_checkinteger(L, 2);
  415. const char *str = luaL_checklstring(L, 3, &len);
  416. eink_str_color = luaL_optinteger(L, 4, 0);
  417. int font = luaL_optinteger(L, 5, 12);
  418. switch (font)
  419. {
  420. case font_opposansm8:
  421. LLOGI("font_opposansm8");
  422. u8g2_SetFont(&(paint.luat_eink_u8g2), u8g2_font_opposansm8);
  423. lua_pushboolean(L, 1);
  424. break;
  425. case font_opposansm10:
  426. LLOGI("font_opposansm10");
  427. u8g2_SetFont(&(paint.luat_eink_u8g2), u8g2_font_opposansm10);
  428. lua_pushboolean(L, 1);
  429. break;
  430. case font_opposansm12:
  431. LLOGI("font_opposansm12");
  432. u8g2_SetFont(&(paint.luat_eink_u8g2), u8g2_font_opposansm12);
  433. lua_pushboolean(L, 1);
  434. break;
  435. case font_opposansm16:
  436. LLOGI("font_opposansm16");
  437. u8g2_SetFont(&(paint.luat_eink_u8g2), u8g2_font_opposansm16);
  438. lua_pushboolean(L, 1);
  439. break;
  440. case font_opposansm18:
  441. LLOGI("font_opposansm18");
  442. u8g2_SetFont(&(paint.luat_eink_u8g2), u8g2_font_opposansm18);
  443. lua_pushboolean(L, 1);
  444. break;
  445. case font_opposansm20:
  446. LLOGI("font_opposansm20");
  447. u8g2_SetFont(&(paint.luat_eink_u8g2), u8g2_font_opposansm20);
  448. lua_pushboolean(L, 1);
  449. break;
  450. case font_opposansm22:
  451. LLOGI("font_opposansm22");
  452. u8g2_SetFont(&(paint.luat_eink_u8g2), u8g2_font_opposansm22);
  453. lua_pushboolean(L, 1);
  454. break;
  455. case font_opposansm24:
  456. LLOGI("font_opposansm24");
  457. u8g2_SetFont(&(paint.luat_eink_u8g2), u8g2_font_opposansm24);
  458. lua_pushboolean(L, 1);
  459. break;
  460. case font_opposansm32:
  461. LLOGI("font_opposansm32");
  462. u8g2_SetFont(&(paint.luat_eink_u8g2), u8g2_font_opposansm32);
  463. lua_pushboolean(L, 1);
  464. break;
  465. #if defined USE_U8G2_OPPOSANSM12_CHINESE
  466. case font_opposansm12_chinese:
  467. LLOGI("font_opposansm12_chinese");
  468. u8g2_SetFont(&(paint.luat_eink_u8g2), u8g2_font_opposansm12_chinese);
  469. lua_pushboolean(L, 1);
  470. break;
  471. #endif
  472. #if defined USE_U8G2_OPPOSANSM16_CHINESE
  473. case font_opposansm16_chinese:
  474. LLOGI("font_opposansm16_chinese");
  475. u8g2_SetFont(&(paint.luat_eink_u8g2), u8g2_font_opposansm16_chinese);
  476. lua_pushboolean(L, 1);
  477. break;
  478. #endif
  479. #if defined USE_U8G2_OPPOSANSM24_CHINESE
  480. case font_opposansm24_chinese:
  481. LLOGI("font_opposansm24_chinese");
  482. u8g2_SetFont(&(paint.luat_eink_u8g2), u8g2_font_opposansm24_chinese);
  483. lua_pushboolean(L, 1);
  484. break;
  485. #endif
  486. #if defined USE_U8G2_OPPOSANSM32_CHINESE
  487. case font_opposansm32_chinese:
  488. LLOGI("font_opposansm32_chinese");
  489. u8g2_SetFont(&(paint.luat_eink_u8g2), u8g2_font_opposansm32_chinese);
  490. lua_pushboolean(L, 1);
  491. break;
  492. #endif
  493. default:
  494. lua_pushboolean(L, 0);
  495. LLOGI("no font");
  496. break;
  497. }
  498. uint16_t e;
  499. int16_t delta, sum;
  500. utf8_state = 0;
  501. sum = 0;
  502. for(;;){
  503. e = utf8_next((uint8_t)*str);
  504. if ( e == 0x0ffff )
  505. break;
  506. str++;
  507. if ( e != 0x0fffe ){
  508. delta = u8g2_font_draw_glyph(&(paint.luat_eink_u8g2), x, y, e);
  509. switch(paint.luat_eink_u8g2.font_decode.dir){
  510. case 0:
  511. x += delta;
  512. break;
  513. case 1:
  514. y += delta;
  515. break;
  516. case 2:
  517. x -= delta;
  518. break;
  519. case 3:
  520. y -= delta;
  521. break;
  522. }
  523. sum += delta;
  524. }
  525. }
  526. return 0;
  527. }
  528. /**
  529. 将缓冲区图像输出到屏幕
  530. @api eink.show(x, y)
  531. @int x 输出的x坐标,默认0
  532. @int y 输出的y坐标,默认0
  533. @return nil 无返回值
  534. */
  535. static int l_eink_show(lua_State *L)
  536. {
  537. int x = luaL_optinteger(L, 1, 0);
  538. int y = luaL_optinteger(L, 2, 0);
  539. /* Display the frame_buffer */
  540. //EPD_SetFrameMemory(&epd, frame_buffer, x, y, Paint_GetWidth(&paint), Paint_GetHeight(&paint));
  541. //EPD_DisplayFrame(&epd);
  542. EPD_Clear();
  543. EPD_Display(frame_buffer, NULL);
  544. return 0;
  545. }
  546. /**
  547. 缓冲区绘制线
  548. @api eink.line(x, y, x2, y2, colored)
  549. @int 起点x坐标
  550. @int 起点y坐标
  551. @int 终点x坐标
  552. @int 终点y坐标
  553. @return nil 无返回值
  554. @usage
  555. eink.line(0, 0, 10, 20, 0)
  556. */
  557. static int l_eink_line(lua_State *L)
  558. {
  559. int x = luaL_checkinteger(L, 1);
  560. int y = luaL_checkinteger(L, 2);
  561. int x2 = luaL_checkinteger(L, 3);
  562. int y2 = luaL_checkinteger(L, 4);
  563. int colored = luaL_optinteger(L, 5, 0);
  564. Paint_DrawLine(&paint, x, y, x2, y2, colored);
  565. return 0;
  566. }
  567. /**
  568. 缓冲区绘制矩形
  569. @api eink.rect(x, y, x2, y2, colored, fill)
  570. @int 左上顶点x坐标
  571. @int 左上顶点y坐标
  572. @int 右下顶点x坐标
  573. @int 右下顶点y坐标
  574. @int 默认是0
  575. @int 是否填充,默认是0,不填充
  576. @return nil 无返回值
  577. @usage
  578. eink.rect(0, 0, 10, 20)
  579. eink.rect(0, 0, 10, 20, 1) -- Filled
  580. */
  581. static int l_eink_rect(lua_State *L)
  582. {
  583. int x = luaL_checkinteger(L, 1);
  584. int y = luaL_checkinteger(L, 2);
  585. int x2 = luaL_checkinteger(L, 3);
  586. int y2 = luaL_checkinteger(L, 4);
  587. int colored = luaL_optinteger(L, 5, 0);
  588. int fill = luaL_optinteger(L, 6, 0);
  589. if(fill)
  590. Paint_DrawFilledRectangle(&paint, x, y, x2, y2, colored);
  591. else
  592. Paint_DrawRectangle(&paint, x, y, x2, y2, colored);
  593. return 0;
  594. }
  595. /**
  596. 缓冲区绘制圆形
  597. @api eink.circle(x, y, radius, colored, fill)
  598. @int 圆心x坐标
  599. @int 圆心y坐标
  600. @int 半径
  601. @int 默认是0
  602. @int 是否填充,默认是0,不填充
  603. @return nil 无返回值
  604. @usage
  605. eink.circle(0, 0, 10)
  606. eink.circle(0, 0, 10, 1, 1) -- Filled
  607. */
  608. static int l_eink_circle(lua_State *L)
  609. {
  610. int x = luaL_checkinteger(L, 1);
  611. int y = luaL_checkinteger(L, 2);
  612. int radius = luaL_checkinteger(L, 3);
  613. int colored = luaL_optinteger(L, 4, 0);
  614. int fill = luaL_optinteger(L, 5, 0);
  615. if(fill)
  616. Paint_DrawFilledCircle(&paint, x, y, radius, colored);
  617. else
  618. Paint_DrawCircle(&paint, x, y, radius, colored);
  619. return 0;
  620. }
  621. /**
  622. 缓冲区绘制QRCode
  623. @api eink.qrcode(x, y, str, version)
  624. @int x坐标
  625. @int y坐标
  626. @string 二维码的内容
  627. @int 二维码版本号
  628. @return nil 无返回值
  629. */
  630. static int l_eink_qrcode(lua_State *L)
  631. {
  632. size_t len;
  633. int x = luaL_checkinteger(L, 1);
  634. int y = luaL_checkinteger(L, 2);
  635. const char* str = luaL_checklstring(L, 3, &len);
  636. int version = luaL_checkinteger(L, 4);
  637. // Create the QR code
  638. QRCode qrcode;
  639. uint8_t qrcodeData[qrcode_getBufferSize(version)];
  640. qrcode_initText(&qrcode, qrcodeData, version, 0, str);
  641. for(int i = 0; i < qrcode.size; i++)
  642. {
  643. for (int j = 0; j < qrcode.size; j++)
  644. {
  645. qrcode_getModule(&qrcode, j, i) ? Paint_DrawPixel(&paint, x+j, y+i, COLORED) : Paint_DrawPixel(&paint, x+j, y+i, UNCOLORED);
  646. }
  647. }
  648. return 0;
  649. }
  650. /**
  651. 缓冲区绘制电池
  652. @api eink.bat(x, y, bat)
  653. @int x坐标
  654. @int y坐标
  655. @int 电池电压,单位毫伏
  656. @return nil 无返回值
  657. */
  658. static int l_eink_bat(lua_State *L)
  659. {
  660. int x = luaL_checkinteger(L, 1);
  661. int y = luaL_checkinteger(L, 2);
  662. int bat = luaL_checkinteger(L, 3);
  663. int batnum = 0;
  664. // eink.rect(0, 3, 2, 6)
  665. // eink.rect(2, 0, 20, 9)
  666. // eink.rect(9, 1, 19, 8, 0, 1)
  667. if(bat < 4200 && bat > 4080)batnum = 100;
  668. if(bat < 4080 && bat > 4000)batnum = 90;
  669. if(bat < 4000 && bat > 3930)batnum = 80;
  670. if(bat < 3930 && bat > 3870)batnum = 70;
  671. if(bat < 3870 && bat > 3820)batnum = 60;
  672. if(bat < 3820 && bat > 3790)batnum = 50;
  673. if(bat < 3790 && bat > 3770)batnum = 40;
  674. if(bat < 3770 && bat > 3730)batnum = 30;
  675. if(bat < 3730 && bat > 3700)batnum = 20;
  676. if(bat < 3700 && bat > 3680)batnum = 15;
  677. if(bat < 3680 && bat > 3500)batnum = 10;
  678. if(bat < 3500 && bat > 2500)batnum = 5;
  679. batnum = 20 - (int)(batnum / 5) + 3;
  680. // w外框
  681. Paint_DrawRectangle(&paint, x+0, y+3, x+2, y+6, COLORED);
  682. Paint_DrawRectangle(&paint, x+2, y+0, x+23, y+9, COLORED);
  683. // 3 ~21 100 / 5
  684. Paint_DrawFilledRectangle(&paint, x+batnum, y+1, x+22, y+8, COLORED);
  685. return 0;
  686. }
  687. /**
  688. 缓冲区绘制天气图标
  689. @api eink.weather_icon(x, y, code)
  690. @int x坐标
  691. @int y坐标
  692. @int 天气代号
  693. @return nil 无返回值
  694. */
  695. static int l_eink_weather_icon(lua_State *L)
  696. {
  697. size_t len;
  698. int x = luaL_checkinteger(L, 1);
  699. int y = luaL_checkinteger(L, 2);
  700. int code = luaL_checkinteger(L, 3);
  701. const char* str = luaL_optlstring(L, 4, "nil", &len);
  702. const unsigned char * icon = gImage_999;
  703. if (strcmp(str, "xue") == 0)code = 401;
  704. if (strcmp(str, "lei") == 0)code = 302;
  705. if (strcmp(str, "shachen") == 0)code = 503;
  706. if (strcmp(str, "wu") == 0)code = 501;
  707. if (strcmp(str, "bingbao") == 0)code = 504;
  708. if (strcmp(str, "yun") == 0)code = 103;
  709. if (strcmp(str, "yu") == 0)code = 306;
  710. if (strcmp(str, "yin") == 0)code = 101;
  711. if (strcmp(str, "qing") == 0)code = 100;
  712. // xue、lei、shachen、wu、bingbao、yun、yu、yin、qing
  713. //if(code == 64)
  714. // for(int i = 0; i < 64; i++)
  715. // {
  716. // for (int j = 0; j < 8; j++)
  717. // {
  718. // for (int k = 0; k < 8; k++)
  719. // (gImage_103[i*8+j] << k )& 0x80 ? Paint_DrawPixel(&paint, x+j*8+k, y+i, COLORED) : Paint_DrawPixel(&paint, x+j*8+k, y+i, UNCOLORED);
  720. // }
  721. // }
  722. switch (code)
  723. {
  724. case 100:icon = gImage_100;break;
  725. case 101:icon = gImage_101;break;
  726. case 102:icon = gImage_102;break;
  727. case 103:icon = gImage_103;break;
  728. case 104:icon = gImage_104;break;
  729. case 200:icon = gImage_200;break;
  730. case 201:icon = gImage_201;break;
  731. case 205:icon = gImage_205;break;
  732. case 208:icon = gImage_208;break;
  733. case 301:icon = gImage_301;break;
  734. case 302:icon = gImage_302;break;
  735. case 303:icon = gImage_303;break;
  736. case 304:icon = gImage_304;break;
  737. case 305:icon = gImage_305;break;
  738. case 306:icon = gImage_306;break;
  739. case 307:icon = gImage_307;break;
  740. case 308:icon = gImage_308;break;
  741. case 309:icon = gImage_309;break;
  742. case 310:icon = gImage_310;break;
  743. case 311:icon = gImage_311;break;
  744. case 312:icon = gImage_312;break;
  745. case 313:icon = gImage_313;break;
  746. case 400:icon = gImage_400;break;
  747. case 401:icon = gImage_401;break;
  748. case 402:icon = gImage_402;break;
  749. case 403:icon = gImage_403;break;
  750. case 404:icon = gImage_404;break;
  751. case 405:icon = gImage_405;break;
  752. case 406:icon = gImage_406;break;
  753. case 407:icon = gImage_407;break;
  754. case 500:icon = gImage_500;break;
  755. case 501:icon = gImage_501;break;
  756. case 502:icon = gImage_502;break;
  757. case 503:icon = gImage_503;break;
  758. case 504:icon = gImage_504;break;
  759. case 507:icon = gImage_507;break;
  760. case 508:icon = gImage_508;break;
  761. case 900:icon = gImage_900;break;
  762. case 901:icon = gImage_901;break;
  763. case 999:icon = gImage_999;break;
  764. default:
  765. break;
  766. }
  767. for(int i = 0; i < 48; i++)
  768. {
  769. for (int j = 0; j < 6; j++)
  770. {
  771. for (int k = 0; k < 8; k++)
  772. (icon[i*6+j] << k )& 0x80 ? Paint_DrawPixel(&paint, x+j*8+k, y+i, COLORED) : Paint_DrawPixel(&paint, x+j*8+k, y+i, UNCOLORED);
  773. }
  774. }
  775. return 0;
  776. }
  777. /**
  778. 设置墨水屏驱动型号
  779. @api eink.model(m)
  780. @int 型号名称, 例如 eink.model(eink.MODEL_1in54_V2)
  781. @return nil 无返回值
  782. */
  783. static int l_eink_model(lua_State *L) {
  784. EPD_Model(luaL_checkinteger(L, 1));
  785. return 0;
  786. }
  787. #ifdef LUAT_USE_GTFONT
  788. #include "GT5SLCD2E_1A.h"
  789. 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);
  790. 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);
  791. static int l_eink_draw_gtfont_gb2312(lua_State *L) {
  792. unsigned char buf[128];
  793. int len;
  794. int i = 0;
  795. uint8_t strhigh,strlow ;
  796. uint16_t str;
  797. const char *fontCode = luaL_checklstring(L, 1,&len);
  798. unsigned char size = luaL_checkinteger(L, 2);
  799. int x = luaL_checkinteger(L, 3);
  800. int y = luaL_checkinteger(L, 4);
  801. while ( i < len){
  802. strhigh = *fontCode;
  803. fontCode++;
  804. strlow = *fontCode;
  805. str = (strhigh<<8)|strlow;
  806. fontCode++;
  807. get_font(buf, 1, str, size, size, size);
  808. gtfont_draw_w(buf , x ,y , size , size,Paint_DrawPixel,&paint,1);
  809. x+=size;
  810. i+=2;
  811. }
  812. return 0;
  813. }
  814. static int l_eink_draw_gtfont_gb2312_gray(lua_State* L) {
  815. unsigned char buf[2048];
  816. int len;
  817. int i = 0;
  818. uint8_t strhigh,strlow ;
  819. uint16_t str;
  820. const char *fontCode = luaL_checklstring(L, 1,&len);
  821. unsigned char size = luaL_checkinteger(L, 2);
  822. unsigned char font_g = luaL_checkinteger(L, 3);
  823. int x = luaL_checkinteger(L, 4);
  824. int y = luaL_checkinteger(L, 5);
  825. while ( i < len){
  826. strhigh = *fontCode;
  827. fontCode++;
  828. strlow = *fontCode;
  829. str = (strhigh<<8)|strlow;
  830. fontCode++;
  831. get_font(buf, 1, str, size*font_g, size*font_g, size*font_g);
  832. Gray_Process(buf,size,size,font_g);
  833. gtfont_draw_gray_hz(buf, x, y, size , size, font_g, 1,Paint_DrawPixel,&paint,1);
  834. x+=size;
  835. i+=2;
  836. }
  837. return 0;
  838. }
  839. #ifdef LUAT_USE_GTFONT_UTF8
  840. extern unsigned short unicodetogb2312 ( unsigned short chr);
  841. static int l_eink_draw_gtfont_utf8(lua_State *L) {
  842. unsigned char buf[128];
  843. int len;
  844. int i = 0;
  845. uint8_t strhigh,strlow ;
  846. uint16_t e,str;
  847. const char *fontCode = luaL_checklstring(L, 1,&len);
  848. unsigned char size = luaL_checkinteger(L, 2);
  849. int x = luaL_checkinteger(L, 3);
  850. int y = luaL_checkinteger(L, 4);
  851. for(;;){
  852. e = utf8_next((uint8_t)*fontCode);
  853. if ( e == 0x0ffff )
  854. break;
  855. fontCode++;
  856. if ( e != 0x0fffe ){
  857. uint16_t str = unicodetogb2312(e);
  858. get_font(buf, 1, str, size, size, size);
  859. gtfont_draw_w(buf , x ,y , size , size,Paint_DrawPixel,&paint,1);
  860. x+=size;
  861. }
  862. }
  863. return 0;
  864. }
  865. static int l_eink_draw_gtfont_utf8_gray(lua_State* L) {
  866. unsigned char buf[2048];
  867. int len;
  868. int i = 0;
  869. uint8_t strhigh,strlow ;
  870. uint16_t e,str;
  871. const char *fontCode = luaL_checklstring(L, 1,&len);
  872. unsigned char size = luaL_checkinteger(L, 2);
  873. unsigned char font_g = luaL_checkinteger(L, 3);
  874. int x = luaL_checkinteger(L, 4);
  875. int y = luaL_checkinteger(L, 5);
  876. for(;;){
  877. e = utf8_next((uint8_t)*fontCode);
  878. if ( e == 0x0ffff )
  879. break;
  880. fontCode++;
  881. if ( e != 0x0fffe ){
  882. uint16_t str = unicodetogb2312(e);
  883. get_font(buf, 1, str, size*font_g, size*font_g, size*font_g);
  884. Gray_Process(buf,size,size,font_g);
  885. gtfont_draw_gray_hz(buf, x, y, size , size, font_g, 1,Paint_DrawPixel,&paint,1);
  886. x+=size;
  887. }
  888. }
  889. return 0;
  890. }
  891. #endif // LUAT_USE_GTFONT_UTF8
  892. #endif // LUAT_USE_GTFONT
  893. /*
  894. 绘制位图
  895. @api eink.bitmap(x, y, h, data, mode)
  896. @int X坐标
  897. @int y坐标
  898. @int 行数
  899. @int 位图数据,每一位代表一个像素
  900. @int 模式, 0值是否写入. mode=1代表写入, mode=0代表不写入, 默认mode=0
  901. @usage
  902. -- 在(10,10)为左上角,绘制 10x4 的位图
  903. eink.bitmap(10, 10, 10, string.char(0x20, 0xFF, 0xFF, 0xAF, 0xDE), 1)
  904. */
  905. static int l_eink_bitmap(lua_State *L) {
  906. int x = luaL_checkinteger(L, 1);
  907. int y = luaL_checkinteger(L, 2);
  908. int row = luaL_checkinteger(L, 3);
  909. size_t len;
  910. const char* data = luaL_checklstring(L, 4, &len);
  911. int mode = luaL_optinteger(L, 5, 0);
  912. int w = len * 8 / row; // 算出每行的bit数量
  913. uint8_t c = 0;
  914. for (size_t i = 0; i < row; i++) // 行
  915. {
  916. for (size_t j = 0; j < w; j++) // 列
  917. {
  918. c = data[(w*i + j)/8];
  919. if (c & ((1 << ((w*i + j)%8)))) {
  920. Paint_DrawPixel(&paint, x + j, y + row, 1);
  921. }
  922. else if (mode)
  923. Paint_DrawPixel(&paint, x + j, y + row, 0);
  924. }
  925. return 0;
  926. }
  927. }
  928. #include "rotable.h"
  929. static const rotable_Reg reg_eink[] =
  930. {
  931. { "setup", l_eink_setup, 0},
  932. { "clear", l_eink_clear, 0},
  933. { "setWin", l_eink_setWin, 0},
  934. { "getWin", l_eink_getWin, 0},
  935. { "print", l_eink_print, 0},
  936. { "show", l_eink_show, 0},
  937. { "rect", l_eink_rect, 0},
  938. { "circle", l_eink_circle, 0},
  939. { "line", l_eink_line, 0},
  940. { "qrcode", l_eink_qrcode, 0},
  941. { "bat", l_eink_bat, 0},
  942. { "weather_icon", l_eink_weather_icon, 0},
  943. { "model", l_eink_model, 0},
  944. { "bitmap", l_eink_bitmap, 0},
  945. #ifdef LUAT_USE_GTFONT
  946. { "drawGtfontGb2312", l_eink_draw_gtfont_gb2312, 0},
  947. { "drawGtfontGb2312Gray", l_eink_draw_gtfont_gb2312_gray, 0},
  948. #ifdef LUAT_USE_GTFONT_UTF8
  949. { "drawGtfontUtf8", l_eink_draw_gtfont_utf8, 0},
  950. { "drawGtfontUtf8Gray", l_eink_draw_gtfont_utf8_gray, 0},
  951. #endif // LUAT_USE_GTFONT_UTF8
  952. #endif // LUAT_USE_GTFONT
  953. { "MODEL_1in02d", NULL, MODEL_1in02d},
  954. { "MODEL_1in54", NULL, MODEL_1in54},
  955. { "MODEL_1in54_V2", NULL, MODEL_1in54_V2},
  956. { "MODEL_1in54b", NULL, MODEL_1in54b},
  957. { "MODEL_1in54b_V2", NULL, MODEL_1in54b_V2},
  958. { "MODEL_1in54c", NULL, MODEL_1in54c},
  959. { "MODEL_1in54f", NULL, MODEL_1in54f},
  960. { "MODEL_2in54b_V3", NULL, MODEL_2in13b_V3},
  961. { "MODEL_2in7", NULL, MODEL_2in7},
  962. { "MODEL_2in7b", NULL, MODEL_2in7b},
  963. { "MODEL_2in9", NULL, MODEL_2in9},
  964. { "MODEL_2in9_V2", NULL, MODEL_2in9_V2},
  965. { "MODEL_2in9bc", NULL, MODEL_2in9bc},
  966. { "MODEL_2in9b_V3", NULL, MODEL_2in9b_V3},
  967. { "MODEL_2in9d", NULL, MODEL_2in9d},
  968. { "MODEL_2in9f", NULL, MODEL_2in9f},
  969. { "MODEL_3in7", NULL, MODEL_3in7},
  970. { "font_opposansm8", NULL, font_opposansm8},
  971. { "font_opposansm10", NULL, font_opposansm10},
  972. { "font_opposansm12", NULL, font_opposansm12},
  973. { "font_opposansm16", NULL, font_opposansm16},
  974. { "font_opposansm18", NULL, font_opposansm18},
  975. { "font_opposansm20", NULL, font_opposansm20},
  976. { "font_opposansm22", NULL, font_opposansm22},
  977. { "font_opposansm24", NULL, font_opposansm24},
  978. { "font_opposansm32", NULL, font_opposansm32},
  979. { "font_opposansm12_chinese", NULL, font_opposansm12_chinese},
  980. { "font_opposansm16_chinese", NULL, font_opposansm16_chinese},
  981. { "font_opposansm24_chinese", NULL, font_opposansm24_chinese},
  982. { "font_opposansm32_chinese", NULL, font_opposansm32_chinese},
  983. { NULL, NULL, 0}
  984. };
  985. LUAMOD_API int luaopen_eink( lua_State *L ){
  986. luat_newlib(L, reg_eink);
  987. return 1;
  988. }