luat_lib_eink.c 31 KB

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