devterm_thermal_printer.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958
  1. // for ltp02-245
  2. // 203 dpi, 384dots in 48mm(1.88976inch) every dots == 0.125mm,
  3. // 1byte==8dots==1mm make clean && make && ./*.elf
  4. //#include <SPI.h>
  5. #include <fcntl.h>
  6. #include <stdarg.h>
  7. #include <stdint.h>
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <string.h>
  11. #include <sys/stat.h>
  12. #include <unistd.h>
  13. #include <wiringPi.h>
  14. #include "logo.h"
  15. #include "pcf_5x7-ISO8859-1_5x7.h"
  16. #include "pcf_6x12-ISO8859-1_6x12.h"
  17. #include "pcf_7x14-ISO8859-1_7x14.h"
  18. #include "ttf_Px437_PS2thin1_8x16.h"
  19. #include "ttf_Px437_PS2thin2_8x16.h"
  20. #include "config.h"
  21. #include "printer.h"
  22. #include "utils.h"
  23. #include "ftype.h"
  24. #include <math.h>
  25. SerialCache ser_cache;
  26. uint8_t cmd[10];
  27. uint8_t cmd_idx;
  28. uint8_t newline;
  29. char buf[2];
  30. unsigned long time;
  31. ImageCache img_cache;
  32. FONT current_font;
  33. FT_Face face;
  34. FT_Library ft;
  35. CONFIG g_config;
  36. TimeRec battery_chk_tm;
  37. int printf_out(CONFIG *cfg, char *format, ...) {
  38. va_list args;
  39. int rv;
  40. va_start(args, format);
  41. if (cfg->fp != NULL)
  42. rv = vfprintf(cfg->fp, format, args);
  43. else {
  44. rv = -1;
  45. }
  46. va_end(args);
  47. return rv;
  48. }
  49. // void printer_set_font(CONFIG*cfg,uint8_t fnbits);
  50. // void parse_serial_stream(CONFIG*cfg,uint8_t input_ch);
  51. void reset_cmd() {
  52. cmd_idx = 0;
  53. ser_cache.idx = 0;
  54. g_config.state = PRINT_STATE;
  55. }
  56. void init_printer() {
  57. char *error = NULL;
  58. memset(cmd, 0, 10);
  59. newline = 0;
  60. cmd_idx = 0;
  61. img_cache.idx = 0;
  62. img_cache.num = 0;
  63. img_cache.width = 0;
  64. img_cache.need_print = 0;
  65. img_cache.revert_bits = 0;
  66. ser_cache.idx = 0;
  67. ser_cache.utf8idx = 0;
  68. /*
  69. current_font.width=5; current_font.height=7; current_font.data =
  70. font_pcf_5x7_ISO8859_1_5x7; current_font.width=6;current_font.height=12;
  71. current_font.data = font_pcf_6x12_ISO8859_1_6x12; current_font.width=7;
  72. current_font.height=14; current_font.data = font_pcf_7x14_ISO8859_1_7x14;
  73. //current_font.width=8;current_font.height=16; current_font.data=
  74. font_ttf_Px437_ISO8_8x16;
  75. //current_font.width=8;current_font.height=16; current_font.data=
  76. font_ttf_Px437_ISO9_8x16;
  77. current_font.width=8;current_font.height=16; current_font.data=
  78. font_ttf_Px437_PS2thin2_8x16;
  79. */
  80. // auto detect TTF ,switch to FONT_MODE_1
  81. if (getenv("TTF") && access(getenv("TTF"), F_OK) != -1) {
  82. printf("TTF=%s\n", getenv("TTF"));
  83. current_font.width = 12;
  84. current_font.height = 12;
  85. current_font.data = NULL;
  86. current_font.file = getenv("TTF");
  87. current_font.mode = FONT_MODE_1;
  88. if (init_ft(current_font.file, &face, &ft, current_font.width,
  89. current_font.height, &error)) {
  90. g_config.face = face;
  91. g_config.ft = ft;
  92. } else {
  93. printf("init_ft error %s\n", error);
  94. g_config.face = NULL;
  95. g_config.ft = NULL;
  96. }
  97. }
  98. //default still FONT_MODE_0, comment out below 4 lines to enable unicode printing
  99. current_font.mode = FONT_MODE_0;
  100. current_font.width = 8;
  101. current_font.height = 16;
  102. current_font.data = font_ttf_Px437_PS2thin2_8x16;
  103. g_config.line_space = 0;
  104. g_config.align = ALIGN_LEFT;
  105. g_config.reverse = 0;
  106. g_config.margin.width = 0;
  107. g_config.margin.esgs = 0;
  108. g_config.orient = FORWARD;
  109. g_config.wordgap = 0;
  110. g_config.font = &current_font;
  111. g_config.under_line = 0;
  112. g_config.state = PRINT_STATE;
  113. g_config.img = &img_cache;
  114. g_config.density = 6;
  115. g_config.feed_pitch = 2;
  116. g_config.max_pts = 2;
  117. g_config.lock = 0;
  118. g_config.degree = 0;
  119. battery_chk_tm.time = millis();
  120. battery_chk_tm.last_status = 0;
  121. battery_chk_tm.check = 0;
  122. }
  123. const char url[] = {"Powered by clockworkpi.com"};
  124. void label_print_f(CONFIG *cfg, char *label, float m, char *last) {
  125. char buf[48];
  126. uint8_t i, j;
  127. if (m == -1.0)
  128. sprintf(buf, "%s", last);
  129. else
  130. sprintf(buf, "%0.2f%s", m, last);
  131. j = strlen(buf);
  132. i = 48 - strlen(label) - j - 1;
  133. if (m == -1.0)
  134. sprintf(buf, "%s%*s%s", label, i, "", last);
  135. else
  136. sprintf(buf, "%s%*s%0.2f%s", label, i, "", m, last);
  137. printer_set_font(cfg, 4);
  138. reset_cmd();
  139. for (i = 0; i < strlen(buf); i++) {
  140. parse_serial_stream(cfg, buf[i]);
  141. }
  142. parse_serial_stream(cfg, 10);
  143. reset_cmd();
  144. }
  145. void label_print_i(CONFIG *cfg, char *label, int m, char *last) {
  146. char buf[MAXPIXELS];
  147. uint8_t i, j;
  148. if (m == -1)
  149. sprintf(buf, "%s", last);
  150. else
  151. sprintf(buf, "%d%s", m, last);
  152. j = strlen(buf);
  153. i = MAXPIXELS - strlen(label) - j - 1;
  154. if (m == -1)
  155. sprintf(buf, "%s%*s%s", label, i, "", last);
  156. else
  157. sprintf(buf, "%s%*s%d%s", label, i, "", m, last);
  158. printer_set_font(cfg, 4);
  159. reset_cmd();
  160. for (i = 0; i < strlen(buf); i++) {
  161. parse_serial_stream(cfg, buf[i]);
  162. }
  163. parse_serial_stream(cfg, 10);
  164. reset_cmd();
  165. }
  166. void printer_test(CONFIG *cfg) {
  167. uint8_t i, j;
  168. uint8_t ch;
  169. uint16_t k;
  170. char buf[MAXPIXELS];
  171. char *font_names[] = {"8x16thin_1", "5x7_ISO8859_1", "6x12_ISO8859_1",
  172. "7x14_ISO8859_1", "8x16thin_2", NULL};
  173. /*
  174. char *selftest1[] = {
  175. " _ __ _ _ ",
  176. " ___ ___| |/ _| | |_ ___ ___| |_ ",
  177. "/ __|/ _ \\ | |_ | __/ _ \\/ __| __|",
  178. "\\__ \\ __/ | _| | || __/\\__ \\ |_ ",
  179. "|___/\\___|_|_| \\__\\___||___/\\__|",
  180. NULL
  181. };
  182. */
  183. char *selftest2[] = {
  184. " #### ###### # ###### ##### ###### #### #####",
  185. "# # # # # # # # ",
  186. " #### ##### # ##### # ##### #### # ",
  187. " # # # # # # # # ",
  188. "# # # # # # # # # # ",
  189. " #### ###### ###### # # ###### #### # ",
  190. NULL};
  191. cfg->density = 6;
  192. k = (os120_width / 8) * os120_height;
  193. memcpy(cfg->img->cache, os120_bits, k);
  194. cfg->img->width = os120_width / 8;
  195. cfg->img->num = k;
  196. cfg->img->revert_bits = 1;
  197. cfg->align = ALIGN_CENTER;
  198. print_image8(cfg);
  199. cfg->img->revert_bits = 0;
  200. cfg->align = ALIGN_LEFT;
  201. print_lines8(NULL,15, cfg->orient);
  202. cfg->align = ALIGN_CENTER;
  203. /* //selftest1
  204. for(i=0;i<5;i++){
  205. printer_set_font(cfg,0);
  206. reset_cmd();
  207. for(j=0;j<strlen(selftest1[i]);j++){
  208. parse_serial_stream(cfg,selftest1[i][j]);
  209. }
  210. parse_serial_stream(cfg,10);
  211. }
  212. */
  213. for (i = 0; i < 6; i++) {
  214. printer_set_font_mode(cfg, FONT_MODE_0);
  215. printer_set_font(cfg, 1);
  216. reset_cmd();
  217. for (j = 0; j < strlen(selftest2[i]); j++) {
  218. parse_serial_stream(cfg, selftest2[i][j]);
  219. }
  220. parse_serial_stream(cfg, 10);
  221. }
  222. cfg->align = ALIGN_LEFT;
  223. print_lines8(NULL,32, cfg->orient);
  224. //---------------------------------------------
  225. for (i = 1; i < 4; i++) {
  226. printer_set_font_mode(cfg, FONT_MODE_0);
  227. printer_set_font(cfg, 0);
  228. reset_cmd();
  229. for (j = 0; j < strlen(font_names[i]); j++) {
  230. parse_serial_stream(cfg, font_names[i][j]);
  231. }
  232. parse_serial_stream(cfg, 10);
  233. printer_set_font_mode(cfg, FONT_MODE_0);
  234. printer_set_font(cfg, i);
  235. reset_cmd();
  236. for (ch = 33; ch < 127; ch++) {
  237. parse_serial_stream(cfg, ch);
  238. // Serial.print(ch,DEC);
  239. }
  240. parse_serial_stream(cfg, 10);
  241. // Serial.println();
  242. print_lines8(NULL,48, cfg->orient);
  243. }
  244. printer_set_font_mode(cfg, FONT_MODE_0);
  245. printer_set_font(cfg, 0);
  246. reset_cmd();
  247. for (j = 0; j < strlen(font_names[0]); j++) {
  248. parse_serial_stream(cfg, font_names[0][j]);
  249. }
  250. parse_serial_stream(cfg, 10);
  251. printer_set_font_mode(cfg, FONT_MODE_0);
  252. printer_set_font(cfg, 0);
  253. reset_cmd();
  254. for (ch = 33; ch < 127; ch++) {
  255. parse_serial_stream(cfg, ch);
  256. // Serial.print(ch,DEC);
  257. }
  258. parse_serial_stream(cfg, 10);
  259. // Serial.println();
  260. print_lines8(NULL,48, cfg->orient);
  261. printer_set_font_mode(cfg, FONT_MODE_0);
  262. printer_set_font(cfg, 0);
  263. reset_cmd();
  264. for (j = 0; j < strlen(font_names[0]); j++) {
  265. parse_serial_stream(cfg, font_names[4][j]);
  266. }
  267. parse_serial_stream(cfg, 10);
  268. printer_set_font_mode(cfg, FONT_MODE_0);
  269. printer_set_font(cfg, 4);
  270. reset_cmd();
  271. for (ch = 33; ch < 127; ch++) {
  272. parse_serial_stream(cfg, ch);
  273. // Serial.print(ch,DEC);
  274. }
  275. parse_serial_stream(cfg, 10);
  276. // Serial.println();
  277. print_lines8(NULL,28, cfg->orient);
  278. //-------------------------------------------
  279. k = temperature();
  280. label_print_i(cfg, "Temperature:", k, " C");
  281. //--------------------------------------------------------
  282. label_print_i(cfg, "Darkness setting:", cfg->density, " (Light 0-15 Dark)");
  283. label_print_i(cfg, "Paper width:", -1, "58mm");
  284. label_print_i(cfg, "Print width:", -1, "48mm");
  285. label_print_i(cfg, "Baudrate:", 115200, "");
  286. label_print_i(cfg, "Data bits:", 8, "");
  287. label_print_i(cfg, "Stop bits:", 1, "");
  288. //------------------------------------------
  289. //------------------------------------------
  290. label_print_f(cfg, "Firmware version:", 0.1, "");
  291. print_lines8(NULL,cfg->font->height, cfg->orient);
  292. //--------------------------------------------------------------
  293. printer_set_font_mode(cfg, FONT_MODE_0);
  294. printer_set_font(cfg, 0);
  295. reset_cmd();
  296. // Serial.println(strlen(url),DEC);
  297. for (i = 0; i < strlen(url); i++) {
  298. parse_serial_stream(cfg, url[i]);
  299. }
  300. parse_serial_stream(cfg, 10);
  301. reset_cmd();
  302. //-----------------------------------
  303. // grid
  304. ENABLE_VH;
  305. for(ch = 0;ch <16;ch++){
  306. if(ch%2==0)
  307. j = 0xff;
  308. else
  309. j = 0x00;
  310. for(k=0;k<8;k++){
  311. for(i=0;i<48;i++){
  312. if(i % 2==0) {
  313. buf[i]=j;
  314. }else{
  315. buf[i]=0xff-j;
  316. }
  317. }
  318. print_dots_8bit_split(cfg,(uint8_t*)buf,48);
  319. }
  320. }
  321. DISABLE_VH;
  322. //--------------------------------------------------------
  323. print_lines8(NULL,cfg->font->height * 2, cfg->orient);
  324. }
  325. void printer_set_font_mode(CONFIG *cfg, int mode) {
  326. cfg->font->mode = mode;
  327. return;
  328. }
  329. void printer_set_font(CONFIG *cfg, uint8_t fnbits) {
  330. uint8_t ret;
  331. ret = MID(fnbits, 0, 3);
  332. if (cfg->font->mode == FONT_MODE_0) {
  333. if (ret == 0) {
  334. cfg->font->width = 8;
  335. cfg->font->height = 16;
  336. cfg->font->data = font_ttf_Px437_PS2thin1_8x16;
  337. }
  338. if (ret == 1) {
  339. cfg->font->width = 5;
  340. cfg->font->height = 7;
  341. cfg->font->data = font_pcf_5x7_ISO8859_1_5x7;
  342. }
  343. if (ret == 2) {
  344. cfg->font->width = 6;
  345. cfg->font->height = 12;
  346. cfg->font->data = font_pcf_6x12_ISO8859_1_6x12;
  347. }
  348. if (ret == 3) {
  349. cfg->font->width = 7;
  350. cfg->font->height = 14;
  351. cfg->font->data = font_pcf_7x14_ISO8859_1_7x14;
  352. }
  353. if (ret == 4) {
  354. cfg->font->width = 8;
  355. cfg->font->height = 16;
  356. cfg->font->data = font_ttf_Px437_PS2thin2_8x16;
  357. }
  358. }
  359. if (cfg->font->mode == FONT_MODE_1) {
  360. if (ret == 0) {
  361. cfg->font->width = 12;
  362. cfg->font->height = 12;
  363. }
  364. if (ret == 1) {
  365. cfg->font->width = 14;
  366. cfg->font->height = 14;
  367. }
  368. if (ret == 2) {
  369. cfg->font->width = 16;
  370. cfg->font->height = 16;
  371. }
  372. if (ret == 3) {
  373. cfg->font->width = 18;
  374. cfg->font->height = 18;
  375. }
  376. if (ret == 4) {
  377. cfg->font->width = 20;
  378. cfg->font->height = 20;
  379. }
  380. change_ft_size(cfg->face, cfg->font->width, cfg->font->height);
  381. }
  382. }
  383. void parse_cmd(CONFIG *cfg, uint8_t *cmd, uint8_t cmdidx) {
  384. uint8_t ret;
  385. if (cmdidx > 1) {
  386. // ESC 2
  387. if (cmd[0] == ASCII_ESC && cmd[1] == 0x32) {
  388. cfg->line_space = cfg->font->height + 8;
  389. reset_cmd();
  390. }
  391. // ESC @
  392. if (cmd[0] == ASCII_ESC && cmd[1] == 0x40) {
  393. init_printer();
  394. reset_cmd();
  395. }
  396. // DC2 T printer test page
  397. if (cmd[0] == ASCII_DC2 && cmd[1] == 0x54) {
  398. reset_cmd();
  399. printer_test(cfg);
  400. }
  401. }
  402. if (cmdidx > 2) {
  403. // ESC j n
  404. if (cmd[0] == ASCII_ESC && cmd[1] == 0x4a) {
  405. if (print_lines8(cfg,0,0) == 0) {
  406. print_lines8(NULL,cmd[2], cfg->orient);
  407. }
  408. reset_cmd();
  409. }
  410. // ESC d n
  411. if (cmd[0] == ASCII_ESC && cmd[1] == 0x64) {
  412. if (print_lines8(cfg,0,0) == 0) {
  413. print_lines8(NULL,cmd[2] * cfg->font->height, cfg->orient);
  414. }
  415. reset_cmd();
  416. }
  417. // ESC ! n
  418. if (cmd[0] == ASCII_ESC && cmd[1] == 0x21) {
  419. ret = cmd[2];
  420. if(ret == 0) {
  421. printer_set_font_mode(cfg,FONT_MODE_0);
  422. printer_set_font(cfg,0);
  423. }else if(ret == 1) {
  424. printer_set_font_mode(cfg,FONT_MODE_1);
  425. printer_set_font(cfg,0);
  426. }
  427. reset_cmd();
  428. }
  429. //GS ! n
  430. if(cmd[0] == ASCII_GS && cmd[1] == 0x21) {
  431. printer_set_font(cfg,cmd[2]);
  432. reset_cmd();
  433. }
  434. // ESC 3 n
  435. if (cmd[0] == ASCII_ESC && cmd[1] == 0x33) {
  436. cfg->line_space = cmd[2];
  437. reset_cmd();
  438. }
  439. // ESC v n
  440. if (cmd[0] == ASCII_ESC && cmd[1] == 0x76) {
  441. if (temperature() > 70) {
  442. ret |= 1 << 6;
  443. }
  444. if ((IsPaper() & NO_PAPER) > 0) {
  445. ret |= 1 << 2;
  446. }
  447. // 1<< 3 == power error
  448. cfg->printf(cfg, "%d", ret);
  449. reset_cmd();
  450. return;
  451. }
  452. // ESC a n
  453. if (cmd[0] == ASCII_ESC && cmd[1] == 0x61) {
  454. ret = cmd[2];
  455. if (ret == 0 || ret == 48) {
  456. cfg->align = ALIGN_LEFT;
  457. }
  458. if (ret == 1 || ret == 49) {
  459. cfg->align = ALIGN_CENTER;
  460. }
  461. if (ret == 2 || ret == 50) {
  462. cfg->align = ALIGN_RIGHT;
  463. }
  464. reset_cmd();
  465. }
  466. // ESC - n
  467. if (cmd[0] == ASCII_ESC && cmd[1] == 0x2d) {
  468. ret = cmd[2];
  469. if (ret == 0 || ret == 48) {
  470. cfg->under_line = 0;
  471. }
  472. if (ret == 1 || ret == 49) {
  473. cfg->under_line = 1;
  474. }
  475. if (ret == 2 || ret == 50) {
  476. cfg->under_line = 2;
  477. }
  478. reset_cmd();
  479. }
  480. // ESC SP n
  481. if (cmd[0] == ASCII_ESC && cmd[1] == 0x20) {
  482. ret = cmd[2];
  483. if (ret + cfg->margin.width < MAX_DOTS) {
  484. cfg->wordgap = ret;
  485. }
  486. reset_cmd();
  487. return;
  488. }
  489. // DC2 # n
  490. if (cmd[0] == ASCII_DC2 && cmd[1] == 0x23) {
  491. ret = cmd[2];
  492. cfg->density = ret;
  493. reset_cmd();
  494. }
  495. // GS V \0 or GS V \1
  496. if (cmd[0] == ASCII_GS && cmd[1] == 0x56) {
  497. ret = cmd[2];
  498. reset_cmd(); // When using parse_serial_stream function internally,
  499. // reset_cmd() first
  500. print_cut_line(cfg);
  501. return;
  502. }
  503. // ESC V n
  504. if (cmd[0] == ASCII_ESC && cmd[1] == 0x56) {
  505. ret = cmd[2];
  506. if (ret == 0x00 || ret == 0x30) {
  507. cfg->degree = 0;
  508. }
  509. if (ret == 0x01 || ret == 0x31) {
  510. cfg->degree = 90;
  511. }
  512. if (ret == 0x02 || ret == 0x32) {
  513. cfg->degree = 180;
  514. }
  515. if (ret == 0x03 || ret == 0x33) {
  516. cfg->degree = 270;
  517. }
  518. printf("set printer degree, %d\n", cfg->degree);
  519. return;
  520. }
  521. }
  522. if (cmdidx > 3) {
  523. // GS L nL nH
  524. if (cmd[0] == ASCII_GS && cmd[1] == 0x4c) {
  525. uint16_t k;
  526. k = cmd[2] + cmd[3] * 256;
  527. if (k < MAX_DOTS - cfg->font->width) {
  528. cfg->margin.width = k;
  529. }
  530. reset_cmd();
  531. }
  532. }
  533. if (cmdidx > 4) {
  534. /*
  535. if(cmd[0] == ASCII_ESC && cmd[1] == 0x2a){
  536. if( cmd[2] == 0 || cmd[2] == 1){
  537. uint16_t k;
  538. k = cmd[3] + 256*cmd[4];
  539. if(k<= IMAGE_MAX){
  540. cfg->state = GET_IMAGE;
  541. cfg->img->num = k;
  542. cfg->img->idx = 0;
  543. }
  544. }
  545. reset_cmd();
  546. }
  547. */
  548. }
  549. if (cmdidx > 7) {
  550. // GS v 0 p wL wH hL hH d1…dk
  551. if (cmd[0] == ASCII_GS && cmd[1] == 118 && cmd[2] == 48) {
  552. uint16_t width = cmd[4] + cmd[5] * 256;
  553. uint16_t height = cmd[6] + cmd[7] * 256;
  554. uint16_t k;
  555. k = width * height;
  556. if (k <= IMAGE_MAX) {
  557. cfg->state = GET_IMAGE;
  558. cfg->img->num = k;
  559. cfg->img->idx = 0;
  560. cfg->img->width = width;
  561. cfg->img->need_print = 1;
  562. }
  563. // do not reset_cmd()
  564. cmd_idx = 0;
  565. ser_cache.idx = 0;
  566. }
  567. }
  568. }
  569. void parse_serial_stream(CONFIG *cfg, uint8_t input_ch) {
  570. uint16_t a;
  571. uint8_t bskip;
  572. if (cfg->state == GET_IMAGE) {
  573. cfg->img->cache[cfg->img->idx] = input_ch;
  574. cfg->img->idx++;
  575. if (cfg->img->idx >= cfg->img->num) { // image full
  576. if (cfg->img->need_print == 1) {
  577. print_image8(cfg);
  578. }
  579. reset_cmd();
  580. cfg->state = PRINT_STATE;
  581. }
  582. } else if (cfg->state == ESC_STATE) {
  583. cmd[cmd_idx] = input_ch;
  584. cmd_idx++;
  585. if (cmd_idx < 10) {
  586. parse_cmd(cfg, cmd, cmd_idx);
  587. } else {
  588. reset_cmd();
  589. }
  590. } else { // PRINT_STATE
  591. switch (input_ch) {
  592. case ASCII_LF:
  593. if (ser_cache.idx == 0) {
  594. print_lines8(NULL,cfg->font->height, cfg->orient);
  595. }
  596. print_lines8(cfg,0,0);
  597. reset_cmd();
  598. break;
  599. case ASCII_FF:
  600. print_lines8(cfg,0,0);
  601. reset_cmd();
  602. break;
  603. case ASCII_DC2:
  604. cmd[cmd_idx] = input_ch;
  605. cfg->state = ESC_STATE;
  606. cmd_idx++;
  607. break;
  608. case ASCII_GS:
  609. cmd[cmd_idx] = input_ch;
  610. cfg->state = ESC_STATE;
  611. cmd_idx++;
  612. break;
  613. case ASCII_ESC:
  614. cmd[cmd_idx] = input_ch;
  615. cfg->state = ESC_STATE;
  616. cmd_idx++;
  617. break;
  618. default:
  619. if (input_ch < 128) {
  620. ser_cache.data[ser_cache.idx] = input_ch;
  621. ser_cache.idx++;
  622. } else { // utf8
  623. // 10xxxxxx bskip == 1
  624. bskip = get_slice_len(input_ch);
  625. if (bskip == 1) {
  626. // append this to int32_t [8:8:8:8] 0xffffffff 4294967295
  627. ser_cache.data[ser_cache.idx] |= input_ch
  628. << (8 * (ser_cache.utf8idx));
  629. if (ser_cache.utf8idx ==
  630. get_slice_len(ser_cache.data[ser_cache.idx] & 0xff) - 1) {
  631. ser_cache.idx++;
  632. ser_cache.utf8idx = 0; // next character
  633. } else {
  634. ser_cache.utf8idx++;
  635. }
  636. }
  637. if (bskip > 1) {
  638. ser_cache.utf8idx = 1;
  639. ser_cache.data[ser_cache.idx] = input_ch;
  640. }
  641. }
  642. // read utf8 codename
  643. //
  644. if (cfg->font->mode == FONT_MODE_1 && cfg->face != NULL) {
  645. a = get_serial_cache_font_width(&g_config);
  646. a += (ser_cache.idx) * 0 + g_config.margin.width;
  647. } else {
  648. a = (ser_cache.idx + 1) * current_font.width + (ser_cache.idx) * 0 +
  649. g_config.margin.width;
  650. }
  651. if (a >= MAX_DOTS) // got enough points to print
  652. {
  653. if (cfg->font->mode == FONT_MODE_1 && cfg->face != NULL ) {
  654. print_lines_ft(cfg,0,0);
  655. } else {
  656. print_lines8(cfg,0,0);
  657. }
  658. reset_cmd();
  659. }
  660. break;
  661. }
  662. }
  663. }
  664. /* Virtual serial port created by socat
  665. socat -d -d pty,link=/tmp/DEVTERM_PRINTER_OUT,raw,echo=0
  666. pty,link=/tmp/DEVTERM_PRINTER_IN,raw,echo=0
  667. */
  668. int read_bat_cap(CONFIG *cfg) {
  669. long ret;
  670. char c[12];
  671. FILE *fptr;
  672. if ((fptr = fopen(BAT_CAP, "r")) == NULL) {
  673. PRINTF("Error! Battery File cannot be opened\n");
  674. // Program exits if the file pointer returns NULL.
  675. return -1;
  676. }
  677. fscanf(fptr, "%[^\n]", c);
  678. // printf("Data from the file:%s\n", c);
  679. fclose(fptr);
  680. ret = strtol(c, NULL, 10);
  681. return (int)ret;
  682. }
  683. int bat_cap_to_pts(CONFIG *cfg, int bat) {
  684. int pts;
  685. pts = (int)round((float)bat / 10.0) + 1;
  686. return pts;
  687. }
  688. void print_lowpower(CONFIG *cfg) {
  689. int i;
  690. char *msg = "Low Power,please charge";
  691. reset_cmd();
  692. printer_set_font(cfg, 4);
  693. for (i = 0; i < strlen(msg); i++) {
  694. parse_serial_stream(cfg, msg[i]);
  695. }
  696. parse_serial_stream(cfg, 10);
  697. reset_cmd();
  698. for (i = 0; i < strlen(msg); i++) {
  699. parse_serial_stream(cfg, msg[i]);
  700. }
  701. parse_serial_stream(cfg, 10);
  702. reset_cmd();
  703. print_lines8(NULL,128, cfg->orient);
  704. printer_set_font(cfg, 0);
  705. PRINTF("%s\n", msg);
  706. }
  707. int check_battery(CONFIG *cfg) {
  708. int bat_cap;
  709. bat_cap = 0;
  710. if (millis() - battery_chk_tm.time > 200) {
  711. bat_cap = read_bat_cap(cfg);
  712. if (bat_cap < 0) {
  713. cfg->max_pts = 1; // no battery ,so set to the slowest
  714. cfg->lock = 0; // unlock printer anyway
  715. PRINTF("no battery,slowest printing\n");
  716. }
  717. if (bat_cap >= 0 && bat_cap <= BAT_THRESHOLD) {
  718. if (cfg->lock == 0) {
  719. print_lowpower(cfg);
  720. }
  721. cfg->lock = 1;
  722. PRINTF("printer locked\n");
  723. reset_cmd(); // clear all serial_cache
  724. } else {
  725. cfg->max_pts = bat_cap_to_pts(cfg, bat_cap);
  726. cfg->lock = 0;
  727. }
  728. battery_chk_tm.time = millis();
  729. }
  730. if (cfg->lock == 1) {
  731. reset_cmd();
  732. }
  733. return 0;
  734. }
  735. #define FIFO_FILE "/tmp/DEVTERM_PRINTER_OUT"
  736. void loop() {
  737. /*
  738. if (Serial.available() > 0) {
  739. // read the incoming byte
  740. Serial.readBytes(buf,1);
  741. parse_serial_stream(&g_config,buf[0]);
  742. }
  743. */
  744. FILE *fp = NULL;
  745. char readbuf[2];
  746. while (1) {
  747. fp = NULL;
  748. fp = fopen(FIFO_FILE, "r+b");
  749. if (fp != NULL) {
  750. g_config.fp = fp;
  751. while (1) {
  752. fread(readbuf, 1, 1, fp);
  753. check_battery(&g_config);
  754. if (g_config.lock == 0) {
  755. // printf("read %x",readbuf[0]);
  756. if (g_config.state == PRINT_STATE) {
  757. if (readbuf[0] == ASCII_TAB) {
  758. readbuf[0] = ' ';
  759. parse_serial_stream(&g_config, readbuf[0]);
  760. parse_serial_stream(&g_config, readbuf[0]);
  761. } else { // not a tab
  762. parse_serial_stream(&g_config, readbuf[0]);
  763. }
  764. } else { // g_config.state != PRINT_STATE
  765. parse_serial_stream(&g_config, readbuf[0]);
  766. }
  767. }
  768. }
  769. fclose(fp);
  770. g_config.fp = NULL;
  771. }
  772. sleep(1);
  773. }
  774. //------------------------------------------
  775. // printer_test(&g_config);
  776. }
  777. void setup() {
  778. wiringPiSetupGpio();
  779. header_init();
  780. header_init1();
  781. clear_printer_buffer();
  782. // Serial.begin(115200);
  783. init_printer();
  784. g_config.printf = &printf_out;
  785. }
  786. int main(int argc, char **argv) {
  787. setup();
  788. loop();
  789. }