printer.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918
  1. #include <glob.h>
  2. #include <math.h>
  3. #include <stdint.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <wiringPi.h>
  8. #include <wiringPiSPI.h>
  9. #include "config.h"
  10. #include "utils.h"
  11. #include "printer.h"
  12. extern FONT current_font;
  13. extern SerialCache ser_cache;
  14. uint16_t STBx[] = {STB1_PIN, STB2_PIN, STB3_PIN, STB4_PIN, STB5_PIN, STB6_PIN};
  15. uint8_t as;
  16. static unsigned int printer_vps_time;
  17. static uint8_t printer_vps_last_status;
  18. static uint8_t printer_temp_check;
  19. static char adc_file_path[128];
  20. static unsigned int printer_last_pitch_time;
  21. static uint8_t acc_time_idx;
  22. static uint16_t acc_time[] = {5459,3459,2762,2314,2028,1828,1675,1553,1456,1374,1302,1242,1191,1144,1103,1065,1031,1000,970,940,910,880};
  23. #define ACCMAX 22
  24. void printer_send_data8(uint8_t w) {
  25. /*
  26. digitalWrite(SPI1_NSS_PIN, LOW); // manually take CSN low for SPI_1
  27. transmission SPI.transfer(w); //Send the HEX data 0x55 over SPI-1 port and
  28. store the received byte to the <data> variable.
  29. //SPI.transfer16(w);
  30. digitalWrite(SPI1_NSS_PIN, HIGH); // manually take CSN high between spi
  31. transmissions
  32. */
  33. wiringPiSPIDataRW(0, &w, 1);
  34. }
  35. void clear_printer_buffer() {
  36. uint8_t i = 0;
  37. for (i = 0; i < 48; i++)
  38. printer_send_data8(0x00);
  39. LATCH_ENABLE;
  40. delayus(1);
  41. LATCH_DISABLE;
  42. delayus(1);
  43. }
  44. uint8_t IsPaper() {
  45. uint8_t status;
  46. uint8_t tmp;
  47. if (millis() - printer_vps_time > 10) {
  48. ENABLE_PEM;
  49. if (ASK4PAPER == LOW) // * LOW is what we want**
  50. {
  51. status = IS_PAPER;
  52. } else {
  53. status = NO_PAPER;
  54. PRINTF("Error:NO PAPER\n");
  55. DISABLE_VH;
  56. }
  57. DISABLE_PEM;
  58. if (printer_temp_check > 20) {
  59. tmp = temperature();
  60. if (tmp >= HOT) {
  61. PRINTF("Printer too Hot\n");
  62. status |= HOT_PRINTER;
  63. DISABLE_VH;
  64. }
  65. printer_temp_check = 0;
  66. } else {
  67. printer_temp_check++;
  68. }
  69. } else {
  70. status = printer_vps_last_status;
  71. }
  72. printer_vps_last_status = status;
  73. printer_vps_time = millis();
  74. return status;
  75. }
  76. uint8_t header_init() {
  77. uint8_t pin[] = {THERMISTORPIN};
  78. uint8_t x;
  79. pinMode(LATCH_PIN, OUTPUT);
  80. for (x = 0; x < STB_NUMBER; x++) {
  81. pinMode(STBx[x], OUTPUT);
  82. digitalWrite(STBx[x], LOW);
  83. }
  84. LATCH_DISABLE;
  85. pinMode(VH_PIN, OUTPUT);
  86. digitalWrite(VH_PIN, LOW);
  87. pinMode(PEM_PIN, INPUT);
  88. // pinMode(PEM_CTL_PIN,OUTPUT);
  89. // adc.setChannels(pin, 1); //this is actually the pin you want to measure
  90. pinMode(THERMISTORPIN, INPUT); // 数字io没有 模拟接口。adc 读温度暂时不搞
  91. /*
  92. //SPI.begin(); //Initialize the SPI_1 port.
  93. SPI.setBitOrder(MSBFIRST); // Set the SPI_1 bit order
  94. SPI.setDataMode(SPI_MODE0); //Set the SPI_1 data mode 0
  95. SPI.setClockDivider(SPI_CLOCK_DIV16); // Slow speed (72 / 16 = 4.5 MHz
  96. SPI_1 speed) SPI.setDataSize(DATA_SIZE_8BIT); SPI.begin(); //Initialize the
  97. SPI_1 port.
  98. */
  99. if (!wiringPiSPISetup(0, 4500000)) {
  100. PRINTF("SPI init failed,exiting...\n");
  101. }
  102. /*
  103. pinMode(SPI1_NSS_PIN, OUTPUT);
  104. digitalWrite(SPI1_NSS_PIN,HIGH);
  105. */
  106. printer_vps_time = 0;
  107. printer_vps_last_status = NO_PAPER;
  108. printer_temp_check = 0;
  109. printer_last_pitch_time = 0;
  110. acc_time_idx = 0;
  111. glob_file(ADC_FILE_PAT);
  112. }
  113. #if 1
  114. uint8_t current_pos = 1;
  115. uint8_t header_init1() {
  116. pinMode(PA_PIN, OUTPUT);
  117. pinMode(PNA_PIN, OUTPUT);
  118. pinMode(PB_PIN, OUTPUT);
  119. pinMode(PNB_PIN, OUTPUT);
  120. as = 0;
  121. return ASK4PAPER;
  122. }
  123. void motor_stepper_pos2(uint8_t position) // forward
  124. {
  125. // position = 9 - position;
  126. // position = (position+1)/2;
  127. if(printer_last_pitch_time == 0) {
  128. acc_time_idx = 0;
  129. }else {
  130. if( millis() - printer_last_pitch_time > 100 ) {
  131. if(READ_VH == LOW) {
  132. acc_time_idx = 0;
  133. }else{
  134. acc_time_idx ++;
  135. if(acc_time_idx > ACCMAX-1) {
  136. acc_time_idx = ACCMAX-1;
  137. }
  138. }
  139. } else {
  140. acc_time_idx ++;
  141. if(acc_time_idx > ACCMAX-1) {
  142. acc_time_idx = ACCMAX-1;
  143. }
  144. }
  145. }
  146. printer_last_pitch_time = millis();
  147. delayMicroseconds(acc_time[acc_time_idx]);
  148. switch (position) {
  149. case 0:
  150. digitalWrite(PA_PIN, LOW);
  151. digitalWrite(PNA_PIN, LOW);
  152. digitalWrite(PB_PIN, LOW);
  153. digitalWrite(PNB_PIN, LOW);
  154. break;
  155. case 1:
  156. digitalWrite(PA_PIN, HIGH);
  157. digitalWrite(PNA_PIN, LOW);
  158. digitalWrite(PB_PIN, LOW);
  159. digitalWrite(PNB_PIN, HIGH);
  160. break;
  161. case 2:
  162. digitalWrite(PA_PIN, HIGH);
  163. digitalWrite(PNA_PIN, LOW);
  164. digitalWrite(PB_PIN, HIGH);
  165. digitalWrite(PNB_PIN, LOW);
  166. break;
  167. case 3:
  168. digitalWrite(PA_PIN, LOW);
  169. digitalWrite(PNA_PIN, HIGH);
  170. digitalWrite(PB_PIN, HIGH);
  171. digitalWrite(PNB_PIN, LOW);
  172. break;
  173. case 4:
  174. digitalWrite(PA_PIN, LOW);
  175. digitalWrite(PNA_PIN, HIGH);
  176. digitalWrite(PB_PIN, LOW);
  177. digitalWrite(PNB_PIN, HIGH);
  178. break;
  179. }
  180. }
  181. uint8_t feed_pitch1(uint64_t lines, uint8_t forward_backward) {
  182. uint8_t pos = current_pos;
  183. uint8_t restor = ~forward_backward;
  184. restor &= 0x01;
  185. if (lines > 0) {
  186. /*
  187. MOTOR_ENABLE1;
  188. MOTOR_ENABLE2;
  189. */
  190. while (lines > 0) {
  191. motor_stepper_pos2(pos); /* 0.0625mm */
  192. if (pos >= 1 && pos <= 4)
  193. pos = pos + (1 - 2 * forward_backward); // adding or subtracting
  194. if (pos < 1 || pos > 4)
  195. pos = pos + (4 - 8 * restor); // restoring pos
  196. lines--;
  197. }
  198. /*
  199. MOTOR_DISABLE1;
  200. MOTOR_DISABLE2;
  201. */
  202. } else {
  203. return ERROR_FEED_PITCH;
  204. }
  205. current_pos = pos;
  206. return 0;
  207. }
  208. void print_dots_8bit_split(CONFIG *cfg, uint8_t *Array, uint8_t characters) {
  209. uint8_t i = 0, y = 0, MAX = MAXPIXELS;
  210. uint8_t blank;
  211. uint16_t pts;
  212. uint8_t temp[MAXPIXELS];
  213. uint8_t _array[MAXPIXELS];
  214. pts = 0;
  215. memcpy(_array, Array, MAXPIXELS);
  216. while ((i < characters) && (i < MAX)) {
  217. pts = pts + bits_number(Array[i]);
  218. if (pts > cfg->max_pts) {
  219. memset(temp, 0, MAXPIXELS);
  220. memcpy(temp, _array, i);
  221. print_dots_8bit(cfg, temp, characters, 0);
  222. pts = bits_number(_array[i]);
  223. memset(_array, 0, i);
  224. } else if (pts == cfg->max_pts) {
  225. memset(temp, 0, MAXPIXELS);
  226. memcpy(temp, _array, i + 1);
  227. print_dots_8bit(cfg, temp, characters, 0);
  228. pts = 0;
  229. memset(_array, 0, i + 1);
  230. }
  231. i++;
  232. }
  233. if (pts > 0) {
  234. print_dots_8bit(cfg, _array, characters, 0);
  235. pts = 0;
  236. }
  237. feed_pitch1(cfg->feed_pitch, cfg->orient);
  238. return;
  239. }
  240. void print_dots_8bit(CONFIG *cfg, uint8_t *Array, uint8_t characters,
  241. uint8_t feed_num) {
  242. uint8_t i = 0, y = 0, MAX = MAXPIXELS;
  243. uint8_t blank;
  244. if (cfg->align == 0) {
  245. while ((i < characters) && (i < MAX)) {
  246. printer_send_data8(Array[i]);
  247. i++;
  248. }
  249. while (i < MAX) {
  250. printer_send_data8(0x00);
  251. i++;
  252. }
  253. } else if (cfg->align == 1) { // center
  254. blank = 0;
  255. blank = (MAX - characters) / 2;
  256. for (i = 0; i < blank; i++) {
  257. printer_send_data8(0x00);
  258. }
  259. for (i = 0; i < characters; i++) {
  260. printer_send_data8(Array[i]);
  261. }
  262. for (i = 0; i < (MAX - characters - blank); i++) {
  263. printer_send_data8(0x00);
  264. }
  265. } else if (cfg->align == 2) {
  266. blank = MAX - characters;
  267. for (i = 0; i < blank; i++) {
  268. printer_send_data8(0x00);
  269. }
  270. for (i = 0; i < characters; i++) {
  271. printer_send_data8(Array[i]);
  272. }
  273. }
  274. LATCH_ENABLE;
  275. delayus(1);
  276. LATCH_DISABLE;
  277. delayMicroseconds(1);
  278. i = 0;
  279. while (y < STB_NUMBER) {
  280. while (i < cfg->density) {
  281. digitalWrite(STBx[y], HIGH);
  282. delayus(HEAT_TIME + cfg->density * 46);
  283. digitalWrite(STBx[y], LOW);
  284. delayus(14);
  285. i++;
  286. }
  287. y++;
  288. }
  289. feed_pitch1(feed_num, cfg->orient);
  290. return;
  291. }
  292. uint16_t read_adc(char *adc_file) {
  293. long ret;
  294. char c[16];
  295. FILE *fptr;
  296. if ((fptr = fopen(adc_file, "r")) == NULL) {
  297. printf("Error! ADC File cannot be opened\n");
  298. // Program exits if the file pointer returns NULL.
  299. return 0;
  300. }
  301. fscanf(fptr, "%[^\n]", c);
  302. // printf("Data from the file:\n%s", c);
  303. fclose(fptr);
  304. ret = strtol(c, NULL, 10);
  305. // printf("the number ret %d\n",ret);
  306. return (uint16_t)ret;
  307. }
  308. uint16_t temperature() {
  309. double Rthermistor = 0, TempThermistor = 0;
  310. uint16_t ADCSamples = 0;
  311. int Sample = 1;
  312. uint16_t ADCConvertedValue;
  313. while (Sample <= NumSamples) {
  314. // ADCSamples += analogRead(THERMISTORPIN); //stm32
  315. ADCSamples += read_adc(adc_file_path);
  316. Sample++;
  317. }
  318. // Thermistor Resistance at x Kelvin
  319. ADCConvertedValue = (double)ADCSamples / NumSamples;
  320. Rthermistor = ((double)ADCResolution / ADCConvertedValue) - 1;
  321. Rthermistor = (double)SeriesResistor / Rthermistor;
  322. // Thermistor temperature in Kelvin
  323. TempThermistor = Rthermistor / RthNominal;
  324. TempThermistor = log(TempThermistor);
  325. TempThermistor /= BCoefficent;
  326. TempThermistor += (1 / (TempNominal + 273.15));
  327. TempThermistor = 1 / TempThermistor;
  328. return (uint16_t)(TempThermistor - 273.15);
  329. // return (uint16_t)(0);
  330. }
  331. int glob_file(char *av) {
  332. glob_t globlist;
  333. if (glob(av, GLOB_PERIOD | GLOB_NOSORT, NULL, &globlist) == GLOB_NOSPACE ||
  334. glob(av, GLOB_PERIOD | GLOB_NOSORT, NULL, &globlist) == GLOB_NOMATCH)
  335. return -1;
  336. if (glob(av, GLOB_PERIOD | GLOB_NOSORT, NULL, &globlist) == GLOB_ABORTED)
  337. return 1;
  338. if (globlist.gl_pathc > 0) {
  339. strcpy(adc_file_path, globlist.gl_pathv[0]);
  340. }
  341. return 0;
  342. }
  343. #endif
  344. uint16_t get_serial_cache_font_width(CONFIG *cfg) {
  345. int i;
  346. uint8_t *ch;
  347. uint32_t codename;
  348. int w;
  349. w = 0;
  350. i = 0;
  351. while (i < ser_cache.idx) {
  352. ch = (uint8_t *)&ser_cache.data[i];
  353. codename = utf8_to_utf32(ch);
  354. FT_UInt gi = FT_Get_Char_Index(cfg->face, codename);
  355. FT_Load_Glyph(cfg->face, gi, FT_LOAD_NO_BITMAP);
  356. w += cfg->face->glyph->metrics.horiAdvance / 64;
  357. i++;
  358. }
  359. return w + cfg->font->width;
  360. }
  361. // print with freetype font dots glyph
  362. uint8_t print_lines_ft(CONFIG *cfg,int lines,int bf) {
  363. uint8_t i, j, k;
  364. int8_t w;
  365. uint8_t dot_line_data[MAXPIXELS];
  366. uint8_t dot_line_idx = 0;
  367. uint8_t dot_line_bitsidx = 0;
  368. uint8_t lastidx, lastw, lastj;
  369. uint8_t row, row_cnt;
  370. uint16_t line_bits;
  371. int8_t left = ser_cache.idx;
  372. uint8_t rv;
  373. if(cfg == NULL && lines > 0) {
  374. ENABLE_VH;
  375. feed_pitch1(lines,bf);
  376. DISABLE_VH;
  377. return 0;
  378. }
  379. line_bits = cfg->margin.width;
  380. dot_line_idx = line_bits / 8;
  381. dot_line_bitsidx = line_bits % 8;
  382. lastidx = 0;
  383. lastw = 0;
  384. lastj = 0;
  385. uint32_t codename;
  386. uint8_t *ch;
  387. //printf("left = %d\n", left);
  388. int line_height = (cfg->face->size->metrics.ascender -
  389. cfg->face->size->metrics.descender) >>
  390. 6;
  391. int baseline_height =
  392. abs(cfg->face->descender) * current_font.height / cfg->face->units_per_EM;
  393. int dpx = 64;
  394. FT_Matrix matrix;
  395. ENABLE_VH;
  396. while (left > 0) {
  397. i = lastidx;
  398. row_cnt = 0;
  399. row = 0;
  400. while (row < line_height) {
  401. line_bits = cfg->margin.width;
  402. dot_line_idx = line_bits / 8;
  403. dot_line_bitsidx = line_bits % 8;
  404. memset(dot_line_data, 0, MAXPIXELS);
  405. // line by line bitmap dots to print
  406. i = lastidx;
  407. while (i < ser_cache.idx) {
  408. ch = (uint8_t *)&ser_cache.data[i];
  409. codename = utf8_to_utf32(ch);
  410. matrix.xx = (FT_Fixed)(cos(((double)cfg->degree / 360) * 3.14159 * 2) *
  411. 0x10000L);
  412. matrix.xy = (FT_Fixed)(-sin(((double)cfg->degree / 360) * 3.14159 * 2) *
  413. 0x10000L);
  414. matrix.yx = (FT_Fixed)(sin(((double)cfg->degree / 360) * 3.14159 * 2) *
  415. 0x10000L);
  416. matrix.yy = (FT_Fixed)(cos(((double)cfg->degree / 360) * 3.14159 * 2) *
  417. 0x10000L);
  418. FT_Set_Transform(cfg->face, &matrix, NULL);
  419. FT_UInt gi = FT_Get_Char_Index(cfg->face, codename);
  420. FT_Load_Glyph(cfg->face, gi, FT_LOAD_DEFAULT);
  421. int y_off = line_height - baseline_height -
  422. cfg->face->glyph->metrics.horiBearingY / dpx;
  423. int glyph_width = cfg->face->glyph->metrics.width / dpx;
  424. int glyph_height = cfg->face->glyph->metrics.height / dpx;
  425. int advance = cfg->face->glyph->metrics.horiAdvance / dpx;
  426. int x_off = (advance - glyph_width) / 2;
  427. int bitmap_rows = cfg->face->glyph->bitmap.rows;
  428. int bitmap_width = cfg->face->glyph->bitmap.width;
  429. // FT_Render_Glyph(cfg->face->glyph, FT_RENDER_MODE_NORMAL);
  430. FT_Render_Glyph(cfg->face->glyph, FT_RENDER_MODE_MONO); // disable AA
  431. j = 0;
  432. w = 0;
  433. if (lastj != 0) {
  434. j = lastj;
  435. }
  436. if (lastw != 0) {
  437. w = lastw;
  438. }
  439. while (w < advance) {
  440. // if(w > 0 && (w%8) == 0) j++;
  441. if (dot_line_bitsidx > 7) {
  442. dot_line_idx++;
  443. dot_line_bitsidx = 0;
  444. }
  445. // unsigned char p = cfg->face->glyph->bitmap.buffer[row *
  446. // cfg->face->glyph->bitmap.pitch + w];
  447. unsigned char p = 0;
  448. int pitch = abs(cfg->face->glyph->bitmap.pitch);
  449. if (w >= x_off && row >= y_off) {
  450. row_cnt = row - y_off;
  451. if (row_cnt < bitmap_rows) {
  452. // p =
  453. // (cfg->face->glyph->bitmap.buffer[row_cnt*cfg->face->glyph->bitmap.pitch+j]
  454. // >> (7-w%8)) & 1;//disable AA
  455. j = (w - x_off) / 8;
  456. p = cfg->face->glyph->bitmap.buffer[row_cnt * pitch + j];
  457. p = p & (128 >> ((w - x_off) & 7));
  458. }
  459. }
  460. if (p) {
  461. //printf("#");
  462. dot_line_data[dot_line_idx] |= 1 << (7 - dot_line_bitsidx);
  463. } else {
  464. //printf("0");
  465. }
  466. dot_line_bitsidx++;
  467. w++;
  468. line_bits++;
  469. if (line_bits >= MAX_DOTS)
  470. break;
  471. }
  472. // word gap
  473. k = 0;
  474. while (k < cfg->wordgap) {
  475. if (dot_line_bitsidx > 7) {
  476. dot_line_idx++;
  477. dot_line_bitsidx = 0;
  478. }
  479. k++;
  480. dot_line_bitsidx++;
  481. line_bits++;
  482. if (line_bits >= MAX_DOTS)
  483. break;
  484. }
  485. if (line_bits < MAX_DOTS) {
  486. i++;
  487. }
  488. if (line_bits >= MAX_DOTS || i >= ser_cache.idx) {
  489. if (row == (line_height - 1)) { // last of the row loop
  490. if (w >= advance) {
  491. lastidx = i + 1;
  492. lastw = 0;
  493. lastj = 0;
  494. } else {
  495. lastidx = i;
  496. lastw = w;
  497. lastj = j;
  498. }
  499. }
  500. break;
  501. }
  502. }
  503. rv = IsPaper();
  504. if (rv == IS_PAPER) {
  505. // DEBUG("dot_line_idx",dot_line_idx);
  506. // DEBUG("dot_line_bits",dot_line_bitsidx);
  507. print_dots_8bit_split(cfg, dot_line_data, dot_line_idx + 1);
  508. }
  509. row++;
  510. //printf("\n");
  511. }
  512. left = left - lastidx;
  513. row = 0;
  514. /*
  515. if(cfg->line_space > cfg->font->height){
  516. feed_pitch1(cfg->line_space - cfg->font->height,cfg->orient);
  517. }
  518. */
  519. }
  520. DISABLE_VH;
  521. }
  522. uint8_t print_lines8(CONFIG *cfg,int lines,int backforward) {
  523. if( cfg == NULL ){
  524. if(lines > 0) {
  525. ENABLE_VH;
  526. feed_pitch1(lines,backforward);
  527. DISABLE_VH;
  528. }
  529. return 0;
  530. }
  531. if (cfg->font->mode == FONT_MODE_1 && cfg->face!=NULL) {
  532. return print_lines_ft(cfg,0,0);
  533. }
  534. uint8_t i, j, k;
  535. int8_t w;
  536. uint8_t *data;
  537. uint8_t row, pad;
  538. uint16_t addr;
  539. uint16_t line_bits;
  540. uint8_t dot_line_data[MAXPIXELS];
  541. uint8_t dot_line_idx = 0;
  542. uint8_t dot_line_bitsidx = 0;
  543. uint8_t lastidx, lastw, lastj;
  544. int8_t left;
  545. uint8_t rv;
  546. pad = current_font.width % BITS8;
  547. if (pad > 0) {
  548. pad = 1;
  549. }
  550. i = 0;
  551. i = current_font.width / BITS8;
  552. pad = i + pad;
  553. row = 0;
  554. rv = IsPaper();
  555. data = (uint8_t *)malloc(sizeof(uint8_t) * (pad + 1));
  556. i = 0;
  557. line_bits = cfg->margin.width;
  558. dot_line_idx = line_bits / 8;
  559. dot_line_bitsidx = line_bits % 8;
  560. left = ser_cache.idx;
  561. lastidx = 0;
  562. lastw = 0;
  563. lastj = 0;
  564. // DEBUG("left",left);
  565. ENABLE_VH;
  566. while (left > 0) {
  567. i = lastidx;
  568. while (row < current_font.height) {
  569. line_bits = cfg->margin.width;
  570. dot_line_idx = line_bits / 8;
  571. dot_line_bitsidx = line_bits % 8;
  572. memset(dot_line_data, 0, MAXPIXELS);
  573. i = lastidx;
  574. // DEBUG("i",i)
  575. // DEBUG("ser_cache.idx",ser_cache.idx)
  576. while (i < ser_cache.idx) {
  577. addr = pad * (uint8_t)ser_cache.data[i] * current_font.height;
  578. for (j = 0; j < pad; j++) {
  579. data[j] = current_font.data[addr + row * pad + j];
  580. }
  581. j = 0;
  582. w = 0;
  583. if (lastj != 0) {
  584. j = lastj;
  585. }
  586. if (lastw != 0) {
  587. w = lastw;
  588. }
  589. while (w < current_font.width) {
  590. if (w > 0 && (w % 8) == 0)
  591. j++;
  592. if (dot_line_bitsidx > 7) {
  593. dot_line_idx++;
  594. dot_line_bitsidx = 0;
  595. }
  596. k = (data[j] >> (7 - (w % 8))) & 1;
  597. // Serial.print(data[j],HEX);
  598. if (k > 0) {
  599. dot_line_data[dot_line_idx] |= 1 << (7 - dot_line_bitsidx);
  600. // Serial.print("1");
  601. }
  602. dot_line_bitsidx++;
  603. w++;
  604. line_bits++;
  605. if (line_bits >= MAX_DOTS)
  606. break;
  607. }
  608. /// word gap
  609. k = 0;
  610. while (k < cfg->wordgap) {
  611. if (dot_line_bitsidx > 7) {
  612. dot_line_idx++;
  613. dot_line_bitsidx = 0;
  614. }
  615. k++;
  616. dot_line_bitsidx++;
  617. line_bits++;
  618. if (line_bits >= MAX_DOTS)
  619. break;
  620. }
  621. if (line_bits < MAX_DOTS) {
  622. i++;
  623. }
  624. if (line_bits >= MAX_DOTS || i >= ser_cache.idx) {
  625. if (row == (current_font.height - 1)) { // last of the row loop
  626. if (w >= current_font.width) {
  627. lastidx = i + 1;
  628. lastw = 0;
  629. lastj = 0;
  630. } else {
  631. lastidx = i;
  632. lastw = w;
  633. lastj = j;
  634. }
  635. }
  636. break;
  637. }
  638. }
  639. rv = IsPaper();
  640. if (rv == IS_PAPER) {
  641. // DEBUG("dot_line_idx",dot_line_idx);
  642. // DEBUG("dot_line_bits",dot_line_bitsidx);
  643. print_dots_8bit_split(cfg, dot_line_data, dot_line_idx + 1);
  644. }
  645. row++;
  646. }
  647. left = left - lastidx;
  648. row = 0;
  649. if (cfg->line_space > cfg->font->height) {
  650. feed_pitch1(cfg->line_space - cfg->font->height, cfg->orient);
  651. }
  652. }
  653. // Serial.println("print ever");
  654. free(data);
  655. DISABLE_VH;
  656. return rv;
  657. }
  658. uint8_t print_image8(CONFIG *cfg) {
  659. uint16_t height;
  660. uint16_t x, y, addr;
  661. uint8_t rv;
  662. uint8_t LinePixels[MAXPIXELS];
  663. uint8_t maxchars = PRINTER_BITS / 8;
  664. height = cfg->img->num / cfg->img->width;
  665. y = 0;
  666. addr = 0;
  667. rv = IsPaper();
  668. ENABLE_VH;
  669. while (y < height) {
  670. x = 0;
  671. while (x < cfg->img->width) {
  672. addr = x + y * cfg->img->width;
  673. if (cfg->img->revert_bits > 0) // LSB
  674. LinePixels[x] = invert_bit(cfg->img->cache[addr]);
  675. else
  676. LinePixels[x] = cfg->img->cache[addr];
  677. x++;
  678. }
  679. rv = IsPaper();
  680. if (rv == IS_PAPER) {
  681. print_dots_8bit_split(cfg, LinePixels, x);
  682. }
  683. // feed_pitch1(FEED_PITCH,cfg->orient);
  684. y++;
  685. }
  686. // feed_pitch1(cfg->feed_pitch,cfg->orient);
  687. cfg->img->need_print = 0;
  688. cfg->img->num = 0;
  689. cfg->img->idx = 0;
  690. cfg->img->width = 0;
  691. DISABLE_VH;
  692. return rv;
  693. }
  694. uint8_t print_gray_image8(CONFIG *cfg) {
  695. uint16_t height;
  696. uint16_t x, y, addr;
  697. uint8_t rv;
  698. uint8_t LinePixels[MAXPIXELS];
  699. uint8_t maxchars = PRINTER_BITS / 8;
  700. height = cfg->img->num / cfg->img->width;
  701. y = 0;
  702. addr = 0;
  703. // gray print uses 4 colors with following convention
  704. // 3N+0th line has cfg->density/4
  705. // 3N+1th line has cfg->density/2
  706. // 3N+2th line has cfg->density
  707. // white pixels should be unset in all 3 lines
  708. uint8_t density = cfg->density;
  709. uint8_t feed_pitch = cfg->feed_pitch;
  710. rv = IsPaper();
  711. ENABLE_VH;
  712. while (y < height) {
  713. x = 0;
  714. while (x < cfg->img->width) {
  715. addr = x + y * cfg->img->width;
  716. if (cfg->img->revert_bits > 0) // LSB
  717. LinePixels[x] = invert_bit(cfg->img->cache[addr]);
  718. else
  719. LinePixels[x] = cfg->img->cache[addr];
  720. x++;
  721. }
  722. rv = IsPaper();
  723. if (rv == IS_PAPER) {
  724. if (y % 3 == 0) {
  725. cfg->density = density / 4;
  726. cfg->feed_pitch = 0;
  727. }
  728. if (y % 3 == 1) {
  729. cfg->density = density / 2;
  730. cfg->feed_pitch = 0;
  731. }
  732. if (y % 3 == 2) {
  733. cfg->density = density;
  734. cfg->feed_pitch = feed_pitch;
  735. }
  736. print_dots_8bit_split(cfg, LinePixels, x);
  737. delayus(HEAT_TIME*2);
  738. }
  739. y++;
  740. }
  741. cfg->img->need_print = 0;
  742. cfg->img->num = 0;
  743. cfg->img->idx = 0;
  744. cfg->img->width = 0;
  745. DISABLE_VH;
  746. return rv;
  747. }
  748. void print_cut_line(CONFIG *cfg) {
  749. uint8_t bs, i;
  750. bs = PRINTER_BITS / cfg->font->width;
  751. bs -= 1;
  752. reset_cmd();
  753. for (i = 0; i < bs; i++) {
  754. if (i % 2 == 0) {
  755. parse_serial_stream(cfg, '=');
  756. } else {
  757. parse_serial_stream(cfg, '-');
  758. }
  759. }
  760. parse_serial_stream(cfg, ASCII_FF);
  761. }