From 72465de4e470a86bd5b60703fe826fa3e4be667d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=A8Rene=20Richarz?= <¨rene.richarz@bluewin.ch¨> Date: Sat, 13 Apr 2019 15:52:37 +0200 Subject: [PATCH] incremental plot implemented --- tek4010 | Bin 39548 -> 39592 bytes tek4010.c | 49 +++++++++++++++++++++++++++--------------- tests/incremental.c | 49 ++++++++++++++++++++++++++++++++++++++++++ tests/incremental.plt | 1 + tests/incremental.png | Bin 0 -> 16254 bytes versions.txt | 1 + 6 files changed, 83 insertions(+), 17 deletions(-) create mode 100644 tests/incremental.c create mode 100644 tests/incremental.plt create mode 100644 tests/incremental.png diff --git a/tek4010 b/tek4010 index dc8b1a104ed308c77629bfd34da1c7421a4661da..0a9cd380814d055ad9c1c230448a99f92a6e7b12 100755 GIT binary patch delta 8276 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 E596}md;kCd delta 8085 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 K2Kec-3I7Y%TY>NZ diff --git a/tek4010.c b/tek4010.c index c7bd8c0..4d6b18e 100755 --- a/tek4010.c +++ b/tek4010.c @@ -65,6 +65,7 @@ // mode 101 ignore until group separator int mode, savemode; +int penDown = 1; extern int leftmargin; @@ -109,7 +110,7 @@ void tek4010_escapeCodeHandler(cairo_t *cr, cairo_t *cr2, int ch) case 5: // ENQ: ask for status and position // not yet implemented, needs to send 7 bytes - printf("ENQ not supported, ignored\n"); + if (DEBUG) printf("ENQ not supported, ignored\n"); mode = 0; break; case 6: break; @@ -141,13 +142,13 @@ void tek4010_escapeCodeHandler(cairo_t *cr, cairo_t *cr2, int ch) case 23: system("scrot --focussed"); mode= 0; break; case 26: // sub - printf("GIN mode not supported, ignored\n"); - mode = 50; + if (DEBUG) printf("GIN mode not supported, ignored\n"); + mode = 0; break; // modes 27 and 29 - 31 are identical in all modes case 28: // record sepatator - printf("Special point plot mode not supported, ignored\n"); + if (DEBUG) printf("Special point plot mode not supported, ignored\n"); mode = 50; break; @@ -177,7 +178,8 @@ void tek4010_escapeCodeHandler(cairo_t *cr, cairo_t *cr2, int ch) case 'l': case 'm': case 'n': - case 'o': printf("Defocussed mode ESC %c not supported, ignored\n", ch); mode = 101; break; + case 'o': if (DEBUG) printf("Defocussed mode ESC %c not supported, ignored\n", ch); + mode = 101; break; // write-trough mode case 'p': ltype = SOLID; writeThroughMode = 1; mode = 101; showCursor = 0; break; @@ -190,7 +192,7 @@ void tek4010_escapeCodeHandler(cairo_t *cr, cairo_t *cr2, int ch) case 'w': ltype = SOLID; writeThroughMode = 1; mode = 101; showCursor = 0; break; default: - printf("ESC %d not supported, ignored\n",ch); + if (DEBUG) printf("ESC %d not supported, ignored\n",ch); mode = 0; break; } @@ -329,8 +331,9 @@ void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first) mode = 1; plotPointMode = 0; goto endDo; - case 30: // record separator >> incremental mode - printf("Special point plot mode not supported, ignored\n"); + case 30: // record separator >> incremental plot mode + if (DEBUG) printf("Incremental point plot mode not supported, ignored\n"); + penDown = 1; mode = 40; goto endDo; case 31: // US, normal mode @@ -397,7 +400,7 @@ void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first) if (ch == 0) return; if (ch == 29) mode = 1; // group separator else if (ch == 28) { plotPointMode = 1; todo = 16 * todo; } - else printf("Plot mode, unknown char %d, plotPointMode = %d\n",ch,plotPointMode); + else if (DEBUG) printf("Plot mode, unknown char %d, plotPointMode = %d\n",ch,plotPointMode); return; } @@ -441,7 +444,7 @@ void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first) else if (tag != 0) { yh = 32 * (ch & 31); mode++; } - else printf("case 5: tag is 0\n"); + else if (DEBUG) printf("case 5: tag is 0\n"); if (DEBUG) printf(">>>>>yh=%d\n",yh); break; case 6: yl = (ch & 31); mode++; @@ -465,11 +468,9 @@ void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first) if (plotPointMode>0.0) { + // draw the point tube_drawPoint(cr, cr2); - // draw the point - - mode = 50; todo--; } @@ -486,13 +487,27 @@ void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first) mode = 5; break; - case 30: + case 30: // escape code handler tek4010_escapeCodeHandler(cr, cr2, ch); break; - case 40: // incremental plot mode, not implemented + case 40: // incremental plot mode tek4010_checkReturnToAlpha(ch); // check for exit + if (DEBUG) printf("Incremental plot mode, ch = %d, penDown = %d\n",ch, penDown); + if (ch == 32) penDown = 0; + else if (ch == 80) penDown = 1; + else if ((ch & 0x70) == 0x40){ + if (ch & 4) tube_y0++; + if (ch & 1) tube_x0++; + if (ch & 8) tube_y0--; + if (ch & 2) tube_x0--; + if (DEBUG) printf("point (%d,%d)\n", tube_x0, tube_y0); + tube_x2 = tube_x0; + tube_y2 = tube_y0; + if (penDown) tube_drawPoint(cr, cr2); + } + else if (DEBUG) printf("Illegal byte 0x%02X in incremental plot\n", ch); break; - case 50: // incremental plot mode, not implemented + case 50: // special plot mode, not implemented tek4010_checkReturnToAlpha(ch); // check for exit break; case 101: @@ -530,7 +545,7 @@ void tek4010_draw(cairo_t *cr, cairo_t *cr2, int first) break; } break; - default: printf("Illegal mode - this is a tek4010decoder error and should not happen\n"); + default: if (DEBUG) printf("Illegal mode - this is a tek4010decoder error and should not happen\n"); break; } endDo:; diff --git a/tests/incremental.c b/tests/incremental.c new file mode 100644 index 0000000..bef8ab8 --- /dev/null +++ b/tests/incremental.c @@ -0,0 +1,49 @@ +#define MAXX 1024 +#define MAXY 680 + +#include +#include + +int xs,ys; + +void startDraw(int x1,int y1) +{ + if (x1 < 0) x1 = 0; + if (x1 >= MAXX) x1 = MAXX -1; + if (y1 < 0) y1 = 0; + if (y1 >= MAXY) y1 = MAXY - 1; + putchar(29); + putchar((y1 >> 5) + 32); + putchar((y1 & 31) + 96); + putchar((x1 >> 5) + 32); + putchar((x1 & 31) + 64); + xs = x1; + ys = y1; +} + +extern void endDraw() +{ + putchar(31); + fflush(stdout); +} + +int main (int argc, char *argv[]) +{ + int i; + startDraw(512,140); + putchar(30); + putchar(80); + for (i =0; i<200; i++) { + putchar(69); + } + for (i =0; i<200; i++) { + putchar(70); + } + for (i =0; i<200; i++) { + putchar(74); + } + for (i =0; i<200; i++) { + putchar(73); + } + endDraw(); +} diff --git a/tests/incremental.plt b/tests/incremental.plt new file mode 100644 index 0000000..8d4baee --- /dev/null +++ b/tests/incremental.plt @@ -0,0 +1 @@ +$l0@PEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJJIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII \ No newline at end of file diff --git a/tests/incremental.png b/tests/incremental.png new file mode 100644 index 0000000000000000000000000000000000000000..f7c944e9e14ce171d96e9aeb4f7ba402e3e6743f GIT binary patch literal 16254 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