printer.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853
  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 < 10) {
  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(lines > 0 && cfg == NULL ){
  524. ENABLE_VH;
  525. feed_pitch1(lines,backforward);
  526. DISABLE_VH;
  527. return 0;
  528. }
  529. if (cfg->font->mode == FONT_MODE_1 && cfg->face!=NULL) {
  530. return print_lines_ft(cfg,0,0);
  531. }
  532. uint8_t i, j, k;
  533. int8_t w;
  534. uint8_t *data;
  535. uint8_t row, pad;
  536. uint16_t addr;
  537. uint16_t line_bits;
  538. uint8_t dot_line_data[MAXPIXELS];
  539. uint8_t dot_line_idx = 0;
  540. uint8_t dot_line_bitsidx = 0;
  541. uint8_t lastidx, lastw, lastj;
  542. int8_t left;
  543. uint8_t rv;
  544. pad = current_font.width % BITS8;
  545. if (pad > 0) {
  546. pad = 1;
  547. }
  548. i = 0;
  549. i = current_font.width / BITS8;
  550. pad = i + pad;
  551. row = 0;
  552. rv = IsPaper();
  553. data = (uint8_t *)malloc(sizeof(uint8_t) * (pad + 1));
  554. i = 0;
  555. line_bits = cfg->margin.width;
  556. dot_line_idx = line_bits / 8;
  557. dot_line_bitsidx = line_bits % 8;
  558. left = ser_cache.idx;
  559. lastidx = 0;
  560. lastw = 0;
  561. lastj = 0;
  562. // DEBUG("left",left);
  563. ENABLE_VH;
  564. while (left > 0) {
  565. i = lastidx;
  566. while (row < current_font.height) {
  567. line_bits = cfg->margin.width;
  568. dot_line_idx = line_bits / 8;
  569. dot_line_bitsidx = line_bits % 8;
  570. memset(dot_line_data, 0, MAXPIXELS);
  571. i = lastidx;
  572. // DEBUG("i",i)
  573. // DEBUG("ser_cache.idx",ser_cache.idx)
  574. while (i < ser_cache.idx) {
  575. addr = pad * (uint8_t)ser_cache.data[i] * current_font.height;
  576. for (j = 0; j < pad; j++) {
  577. data[j] = current_font.data[addr + row * pad + j];
  578. }
  579. j = 0;
  580. w = 0;
  581. if (lastj != 0) {
  582. j = lastj;
  583. }
  584. if (lastw != 0) {
  585. w = lastw;
  586. }
  587. while (w < current_font.width) {
  588. if (w > 0 && (w % 8) == 0)
  589. j++;
  590. if (dot_line_bitsidx > 7) {
  591. dot_line_idx++;
  592. dot_line_bitsidx = 0;
  593. }
  594. k = (data[j] >> (7 - (w % 8))) & 1;
  595. // Serial.print(data[j],HEX);
  596. if (k > 0) {
  597. dot_line_data[dot_line_idx] |= 1 << (7 - dot_line_bitsidx);
  598. // Serial.print("1");
  599. }
  600. dot_line_bitsidx++;
  601. w++;
  602. line_bits++;
  603. if (line_bits >= MAX_DOTS)
  604. break;
  605. }
  606. /// word gap
  607. k = 0;
  608. while (k < cfg->wordgap) {
  609. if (dot_line_bitsidx > 7) {
  610. dot_line_idx++;
  611. dot_line_bitsidx = 0;
  612. }
  613. k++;
  614. dot_line_bitsidx++;
  615. line_bits++;
  616. if (line_bits >= MAX_DOTS)
  617. break;
  618. }
  619. if (line_bits < MAX_DOTS) {
  620. i++;
  621. }
  622. if (line_bits >= MAX_DOTS || i >= ser_cache.idx) {
  623. if (row == (current_font.height - 1)) { // last of the row loop
  624. if (w >= current_font.width) {
  625. lastidx = i + 1;
  626. lastw = 0;
  627. lastj = 0;
  628. } else {
  629. lastidx = i;
  630. lastw = w;
  631. lastj = j;
  632. }
  633. }
  634. break;
  635. }
  636. }
  637. rv = IsPaper();
  638. if (rv == IS_PAPER) {
  639. // DEBUG("dot_line_idx",dot_line_idx);
  640. // DEBUG("dot_line_bits",dot_line_bitsidx);
  641. print_dots_8bit_split(cfg, dot_line_data, dot_line_idx + 1);
  642. }
  643. row++;
  644. }
  645. left = left - lastidx;
  646. row = 0;
  647. if (cfg->line_space > cfg->font->height) {
  648. feed_pitch1(cfg->line_space - cfg->font->height, cfg->orient);
  649. }
  650. }
  651. // Serial.println("print ever");
  652. free(data);
  653. DISABLE_VH;
  654. return rv;
  655. }
  656. uint8_t print_image8(CONFIG *cfg) {
  657. uint16_t height;
  658. uint16_t x, y, addr;
  659. uint8_t rv;
  660. uint8_t LinePixels[MAXPIXELS];
  661. uint8_t maxchars = PRINTER_BITS / 8;
  662. height = cfg->img->num / cfg->img->width;
  663. y = 0;
  664. addr = 0;
  665. rv = IsPaper();
  666. ENABLE_VH;
  667. while (y < height) {
  668. x = 0;
  669. while (x < cfg->img->width) {
  670. addr = x + y * cfg->img->width;
  671. if (cfg->img->revert_bits > 0) // LSB
  672. LinePixels[x] = invert_bit(cfg->img->cache[addr]);
  673. else
  674. LinePixels[x] = cfg->img->cache[addr];
  675. x++;
  676. }
  677. rv = IsPaper();
  678. if (rv == IS_PAPER) {
  679. print_dots_8bit_split(cfg, LinePixels, x);
  680. }
  681. // feed_pitch1(FEED_PITCH,cfg->orient);
  682. y++;
  683. }
  684. // feed_pitch1(cfg->feed_pitch,cfg->orient);
  685. cfg->img->need_print = 0;
  686. cfg->img->num = 0;
  687. cfg->img->idx = 0;
  688. cfg->img->width = 0;
  689. DISABLE_VH;
  690. return rv;
  691. }
  692. void print_cut_line(CONFIG *cfg) {
  693. uint8_t bs, i;
  694. bs = PRINTER_BITS / cfg->font->width;
  695. bs -= 1;
  696. reset_cmd();
  697. for (i = 0; i < bs; i++) {
  698. if (i % 2 == 0) {
  699. parse_serial_stream(cfg, '=');
  700. } else {
  701. parse_serial_stream(cfg, '-');
  702. }
  703. }
  704. parse_serial_stream(cfg, ASCII_FF);
  705. }