summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitri Sokolyuk <demon@dim13.org>2011-08-25 08:55:47 +0000
committerDimitri Sokolyuk <demon@dim13.org>2011-08-25 08:55:47 +0000
commit846de8d8d55fb0b5b20e9743d20f77c21b029f1f (patch)
tree6c30c7dfb30c19999abf7463f4ed5f4b5199fc61
Tek ILDA
-rw-r--r--Makefile11
-rw-r--r--tekilda.c305
-rw-r--r--tekplot.c496
-rw-r--r--tekplot.h45
4 files changed, 857 insertions, 0 deletions
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..2ba8558
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,11 @@
+# $Id$
+
+CFLAGS+= -Wall
+PROG= tekilda
+SRCS= tekilda.c tekplot.c
+OBJS= $(SRCS:.c=.o)
+
+$(PROG): $(OBJS)
+
+clean:
+ @rm -f $(PROG) *.core core *.o
diff --git a/tekilda.c b/tekilda.c
new file mode 100644
index 0000000..2c6a984
--- /dev/null
+++ b/tekilda.c
@@ -0,0 +1,305 @@
+/* $Id$ */
+/*
+ * Copyright (c) 2010 Dimitri Sokolyuk <demon@dim13.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <arpa/inet.h> /* endian conversion */
+#include <sys/time.h> /* endian conversion */
+#include <assert.h>
+#include <err.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "tekplot.h"
+
+struct tri { /* Format 0 (3D Coordinates) */
+ int16_t x;
+ int16_t y;
+ int16_t z;
+ uint8_t color; /* Color Index */
+ uint8_t state; /* State Byte */
+} tri;
+
+struct two { /* Format 1 (2D Coordinates) */
+ int16_t x;
+ int16_t y;
+ uint8_t color; /* Color Index */
+ uint8_t state; /* State Byte */
+} two;
+
+struct color { /* Format 2 (Color Index Palette) */
+ uint8_t r;
+ uint8_t g;
+ uint8_t b;
+} color;
+
+struct head {
+ int8_t magic[4]; /* Signature */
+ int8_t zero[3]; /* Not used, must be zero */
+ uint8_t format; /* Format Type */
+ int8_t name[8]; /* Name */
+ int8_t company[8]; /* Company Name */
+ uint16_t npoints; /* Number of Entries in Data Section */
+ uint16_t fnumner; /* Current Frame Number */
+ uint16_t nframes; /* Total Number of Frames */
+ uint8_t shead; /* Scanner Head */
+ uint8_t future; /* Not used, must be zero */
+} head;
+
+struct coord {
+ int x;
+ int y;
+ int z;
+ int on;
+ int color;
+ struct coord *next;
+};
+
+struct ilda {
+ int format;
+ struct coord *coord;
+ struct ilda *next;
+};
+
+#ifndef __dead
+#define __dead __attribute__((noreturn))
+#endif
+
+int dflag = 0;
+
+struct ilda *grab(FILE *);
+void drop(struct ilda *);
+void settimer(int);
+void usage(void);
+
+struct ilda *
+grab(FILE *fd)
+{
+ struct ilda *ilda, **pilda, *il;
+ struct coord *coord, **pcoord, *c;
+ int i, n;
+ int maxx, maxy, maxz, minx, miny, minz, tmp;
+
+ ilda = NULL;
+ pilda = &ilda;
+
+ maxx = maxy = maxz = 0;
+ minx = miny = minz = 1<<12;
+
+#define C(c) ((((htons(c)) + (1<<15)) % (1<<16)) >> 4)
+
+/* find min and max */
+#define R(p, c) \
+ do { \
+ if ((*p)->c > max##c) \
+ max##c = (*p)->c; \
+ if ((*p)->c < min##c) \
+ min##c = (*p)->c; \
+ } while (0)
+
+ printf("Read Vectors\n");
+
+ while (fread(&head, sizeof(head), 1, fd) > 0) {
+ if (memcmp(head.magic, "ILDA", sizeof(head.magic)))
+ errx(-1, "miss magic");
+
+ *pilda = calloc(1, sizeof(*ilda));
+ assert(*pilda);
+ (*pilda)->format = head.format;
+
+ (*pilda)->coord = NULL;
+ pcoord = &(*pilda)->coord;
+
+ n = ntohs(head.npoints);
+
+ switch (head.format) {
+ case 0:
+ for (i = 0; i < n; i++) {
+ fread(&tri, sizeof(tri), 1, fd);
+ *pcoord = calloc(1, sizeof(*coord));
+ assert(*pcoord);
+ (*pcoord)->x = C(tri.x);
+ R(pcoord, x);
+ (*pcoord)->y = C(tri.y);
+ R(pcoord, y);
+ (*pcoord)->z = C(tri.z);
+ R(pcoord, z);
+ (*pcoord)->on = tri.state;
+ (*pcoord)->color = tri.color;
+ pcoord = &(*pcoord)->next;
+ }
+ break;
+ case 1:
+ for (i = 0; i < n; i++) {
+ fread(&two, sizeof(two), 1, fd);
+ *pcoord = calloc(1, sizeof(*coord));
+ assert(*pcoord);
+ (*pcoord)->x = C(tri.x);
+ R(pcoord, x);
+ (*pcoord)->y = C(tri.y);
+ R(pcoord, y);
+ (*pcoord)->on = tri.state;
+ pcoord = &(*pcoord)->next;
+ }
+ break;
+ case 2:
+ for (i = 0; i < head.npoints; i++) {
+ fread(&color, sizeof(color), 1, fd);
+ /* do nothing, just read ahead */
+ }
+ break;
+ }
+
+ pilda = &(*pilda)->next;
+ }
+
+#undef C
+#undef R
+
+/* normalize */
+#define N(p, c, r, m) \
+ do { \
+ r = max##c - min##c; \
+ if (r) \
+ p->c = (p->c - min##c) * (m - 1) / r; \
+ } while (0)
+
+ printf("Normalize Points\n");
+
+ for (il = ilda; il; il = il->next) {
+ for (c = il->coord; c; c = c->next) {
+ N(c, x, tmp, 4096);
+ N(c, y, tmp, 3120);
+ N(c, z, tmp, 1024);
+ }
+ }
+#undef N
+ printf("Ready to Play\n");
+
+ return ilda;
+}
+
+void
+drop(struct ilda *ilda)
+{
+ struct ilda *nilda;
+ struct coord *coord, *ncoord;
+
+ for (; ilda; ilda = nilda) {
+ nilda = ilda->next;
+ for (coord = ilda->coord; coord; coord = ncoord) {
+ ncoord = coord->next;
+ free(coord);
+ }
+ free(ilda);
+ }
+}
+
+void
+catch(int signo)
+{
+ if (signo != SIGALRM)
+ dflag = 1;
+ return;
+}
+
+int
+main(int argc, char **argv)
+{
+ struct sigaction sa;
+ struct ilda *ilda, *i;
+ struct coord *c;
+ int on, ch;
+ int delay = 40000; /* 25 fps */
+ FILE *input;
+
+ while ((ch = getopt(argc, argv, "d:h")) != -1)
+ switch (ch) {
+ case 'd':
+ delay = 1000 * atoi(optarg);
+ break;
+ case 'h':
+ default:
+ usage();
+ /* NOTREACHED */
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (!argc)
+ usage();
+
+ input = fopen(*argv, "r");
+ if(!input)
+ err(-1, "%s", *argv);
+
+ ilda = grab(input);
+ assert(ilda);
+
+ fclose(input);
+
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ sa.sa_handler = catch;
+ sigaction(SIGALRM, &sa, NULL);
+ sigaction(SIGINT, &sa, NULL);
+ sigaction(SIGTERM, &sa, NULL);
+ sigaction(SIGHUP, &sa, NULL);
+
+ settimer(delay);
+
+ inittek();
+ for (i = ilda; !dflag && i; i = i->next) {
+ page();
+ on = 0; /* first vector is always blank */
+ for (c = i->coord; c; c = c->next) {
+ iplot(on, c->x, c->y);
+ on = !c->color;
+ }
+ fflush(stdout);
+ sigsuspend(&sa.sa_mask);
+ }
+ endtek();
+
+ drop(ilda);
+
+ return 0;
+}
+
+void
+settimer(int usec)
+{
+ struct itimerval itv;
+
+ itv.it_value.tv_sec = 0;
+ itv.it_value.tv_usec = usec;
+ itv.it_interval = itv.it_value;
+
+ setitimer(ITIMER_REAL, &itv, NULL);
+}
+
+__dead void
+usage(void)
+{
+ extern char *__progname;
+
+ (void)fprintf(stderr, "usage: %s [-d msec] [ILDA]\n", __progname);
+
+ exit(1);
+}
diff --git a/tekplot.c b/tekplot.c
new file mode 100644
index 0000000..d074f9d
--- /dev/null
+++ b/tekplot.c
@@ -0,0 +1,496 @@
+/* $Id$ */
+
+#include <ctype.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include "tekplot.h"
+
+#define EXTRABITS 0x0f
+#define FIVEBITS 0x1f
+#define HIBITS (FIVEBITS << SHIFTHI)
+#define LOBITS (FIVEBITS << SHIFTLO)
+#define SHIFTHI 7
+#define SHIFTLO 2
+#define TWOBITS 0x03
+
+#define ETX 3 /* VT page */
+#define ENQ 5
+#define BELL 7
+#define BS 010 /* dec char spacing */
+#define HT 011 /* inc char spacing */
+#define LF 012 /* dec line spacing */
+#define VT 013 /* inc line spacing */
+#define FF 014 /* TEX page */
+#define CR 015 /* Alpha mode */
+#define SO 016
+#define SI 017
+#define SUB 032 /* Graphics-in mode */
+#define ESC 033
+#define FS 034 /* Point mode */
+#define GS 035 /* Graphic mode */
+#define RS 036 /* IPlot mode */
+#define US 037 /* Alpha mode */
+#define DEL 0177 /* more esc */
+
+#define TEXT US
+#define PEN GS
+#define DOT FS
+#define GIN SUB
+#define PAGE FF
+#define VTPAGE 3
+
+enum { ALPHA, VECTOR, POINT, SPOINT, SPOINTFETCH, IPLOT, CROSSHAIR } plotf;
+
+#define psleep(t) usleep(1000 * (t)) /* Sleep for t milliseconds */
+
+struct disps {
+ int scrnx[2];
+ int scrny[2];
+} dispxy;
+
+int ohy, oly, ohx, oex;
+int lastx, lasty;
+
+int side = 0;
+int teklf = 90;
+int Mechanical = 0;
+
+int Notatty; /* Output is not a tty - likely pipe to phys */
+int waitflash;
+int XTerm; /* running under XTerm */
+
+static int pen, maxx, oldx, oldy;
+#if 0
+static char Zxystring[] = "4507430165672321";
+#endif
+static char xystring[] = "BJAIBFAEHJHIDFDE";
+
+
+static const char pendown[] = "P";
+static const char penup[] = " ";
+
+void
+esc(char c)
+{
+ putchar(ESC);
+ putchar(c);
+ fflush(stdout);
+}
+
+void
+xycvt(int x, int y)
+{
+ int c;
+ char *p;
+ char pbuf[8];
+ p = pbuf;
+ *p++ = 0;
+
+ /* queue low order x */
+ *p++ = ((x >> SHIFTLO) & FIVEBITS) | 0x40;
+
+ /* if hi x changed, queue it and force xmsn of low order y */
+ if (ohx != (c = ((x >> SHIFTHI) & FIVEBITS) | 0x20))
+ *p++ = oly = ohx = c;
+
+ /* calculate extra byte */
+ c = (x & TWOBITS) | ((y & TWOBITS) << SHIFTLO) | 0x60;
+ if (y & 0x1000)
+ c |= 020;
+
+ /* queue lo y and extra if extra changed */
+ if (oex != c) {
+ *p++ = oly = ((y >> SHIFTLO) & FIVEBITS) | 0x60;
+ *p++ = oex = c;
+ } else if (oly != (c = ((y >> SHIFTLO) & FIVEBITS) | 0x60))
+ *p++ = oly = c;
+
+ if (ohy != (c = ((y >> SHIFTHI) & FIVEBITS) | 0x20))
+ *p++ = ohy = c;
+
+ while ((c = *--p))
+ putchar(c);
+
+ if (waitflash) {
+ if (((abs(x - lastx) > 1500) || (abs(y - lasty) > 1500)) && (plotf == VECTOR))
+ ohy = oly = ohx = oex = 0;
+ lastx = x;
+ lasty = y;
+ }
+}
+
+/*
+ * i = 0 dark vector
+ * i = -1 point plot
+ * i = -32 to -126 special point plot z axis setting
+ */
+
+void
+iplot(int i, int ix, int iy)
+{
+
+ if (Mechanical) {
+ xyplot(i, ix, iy);
+ return;
+ }
+ if (iy < 0 || iy > 4095 || ix < 0 || ix > 4095)
+ return; /* crude clip */
+
+ if (i <= 0) {
+ switch (i) {
+ case -1:
+ if (plotf != POINT) {
+ putchar(DOT);
+ plotf = POINT;
+ }
+ break;
+ case 0:
+ if (plotf != VECTOR && plotf != ALPHA)
+ putchar(TEXT);
+ putchar(PEN);
+ plotf = VECTOR;
+ break;
+ default:
+ if (plotf != SPOINT) {
+ if (plotf != ALPHA)
+ putchar(TEXT);
+
+ putchar(ESC);
+ putchar(DOT);
+
+ plotf = SPOINT;
+ }
+ i = -i;
+ if (i > 125)
+ i = 125;
+ if (i < 32)
+ i = 32;
+ putchar(i);
+ break;
+ }
+ }
+ xycvt(ix, iy);
+ return;
+}
+
+void
+alpha(void)
+{
+ if (Mechanical)
+ printf(penup);
+
+ if (waitflash && plotf == VECTOR) {
+ putchar(0);
+ putchar(0);
+ putchar(0);
+ putchar(0);
+ }
+ plotf = ALPHA;
+ pen = 1;
+ lastx = -1;
+ lasty = -1;
+ putchar(TEXT);
+ fflush(stdout);
+}
+
+void
+inittek(void)
+{
+ char *p;
+ int t;
+ static int done = 0;
+ if (done)
+ return;
+
+ p = getenv("TERM");
+
+ if (!p)
+ return;
+
+ if ((strncmp(p, "xterm", 5) == 0) || (strcmp(p, "dumb") == 0)) {
+ teklf = 88;
+ XTerm = 1;
+ waitflash = 0;
+
+ printf("%c[?38h", ESC);
+
+ } else if (strcmp(p, "tek4014") == 0)
+ teklf = 88;
+ else {
+ waitflash = isdigit(*p);
+ t = atoi(p);
+ if ((t > 4012) && (t < 4020))
+ teklf = 56;
+ else
+ teklf = 88;
+ }
+
+ done = 1;
+}
+
+void
+endtek(void)
+{
+ if (XTerm) {
+ putchar(TEXT);
+ esc(VTPAGE);
+ }
+}
+
+void
+page(void)
+{
+ inittek();
+
+ fflush(stderr);
+ fflush(stdout);
+
+ if (!isatty(1))
+ psleep(200);
+
+ dispxy.scrnx[0] = 0;
+ dispxy.scrnx[1] = 2048;
+ dispxy.scrny[0] = 3070;
+ dispxy.scrny[1] = 3070;
+
+ ohy = 0;
+ oly = 0;
+ ohx = 0;
+ oex = 0;
+
+ lastx = -1;
+ lasty = -1;
+
+ esc(PAGE);
+ plotf = ALPHA;
+
+ if (waitflash)
+ psleep(1500);
+}
+
+/* VARARGS */
+void
+disp(char *fmt,...)
+{
+ va_list ap;
+ alpha();
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+
+ fflush(stdout);
+}
+
+/* VARARGS */
+void
+spad(char *fmt,...)
+{
+ va_list ap;
+ inittek();
+
+ if ((dispxy.scrny[side] -= teklf) < 0)
+ dispxy.scrny[side] = 0;
+
+ iplot(0, dispxy.scrnx[side], dispxy.scrny[side]);
+
+ alpha();
+
+ va_start(ap, fmt);
+ vprintf(fmt, ap);
+ va_end(ap);
+
+ fflush(stdout);
+ psleep(40);
+}
+
+void
+dispii(char *s, int *t)
+{
+ printf("%s ", s);
+ fflush(stdout);
+ scanf("%d", t);
+}
+
+void
+spadii(char *s, int *t)
+{
+ char line[80];
+ spad(s);
+ fgets(line, 77, stdin);
+ if (line[0])
+ sscanf(line, "%d", t);
+}
+
+void
+spadiid(char *s, int *t)
+{
+ char line[80];
+ spad(s);
+ printf(" [%d]: ", *t);
+ fflush(stdout);
+ fgets(line, 77, stdin);
+ if (line[0])
+ sscanf(line, "%d", t);
+}
+
+void
+xyplot(int i, int ix, int iy)
+{
+
+ if (i == 0) {
+ if (pen)
+ printf(penup);
+ pen = 0;
+ } else if (i < 0) {
+ if (pen)
+ printf(penup);
+ xymove(ix, iy);
+ printf(pendown);
+ printf("AHBD");
+ pen = 1;
+ return;
+ } else if (pen == 0) {
+ printf(pendown);
+ pen++;
+ }
+ xymove(ix, iy);
+}
+
+void
+xymove(int x, int y)
+{
+ int ix, iy, sindex, idelta;
+ int ch1, ch2;
+ if (Mechanical < 0) {
+ iy = -x;
+ x = y;
+ y = iy;
+ }
+ sindex = 0;
+ if (x > maxx)
+ maxx = x;
+
+ if ((ix = (oldx - x)) < 0) {
+ sindex++;
+ ix = -ix;
+ }
+ if ((iy = (oldy - y)) < 0) {
+ sindex += 2;
+ iy = -iy;
+ }
+ if (iy > ix)
+ sindex += 4;
+ else if (ix > iy) {
+ idelta = ix;
+ ix = iy;
+ iy = idelta;
+ }
+ if (iy == 0)
+ return;
+
+ sindex <<= 1;
+
+ ch1 = xystring[sindex];
+ ch2 = xystring[sindex + 1];
+
+#define iless ix
+#define igreat iy
+#define icount sindex
+ icount = iy;
+
+ iless <<= 1;
+ idelta = iless - igreat;
+ igreat <<= 1;
+
+ while (--icount >= 0) {
+ if (idelta >= 0) {
+ putchar(ch2);
+ idelta -= igreat;
+ } else {
+ putchar(ch1);
+ }
+ idelta += iless;
+ }
+ oldx = x;
+ oldy = y;
+}
+
+/*
+ * mech(n)
+ * 0: vectors
+ * >0: incremental plotting
+ * <0: incremental plotting rotated 90 degrees clockwise
+ * on a drum plotter this makes y axis the long one
+ */
+
+void
+mech(int n)
+{
+ pen = 1;
+ alpha();
+ iplot(-1, 0, 0);
+ alpha();
+
+ if (n)
+ putchar(RS);
+
+ printf(penup);
+ Mechanical = n;
+}
+
+/*
+ * xyres()
+ * tells xymove that the pen is at 0,0
+ */
+
+void
+xyres(void)
+{
+ oldx = 0;
+ oldy = 0;
+ maxx = 0;
+}
+
+/*
+ * mpage(idelta)
+ * performs a move to the coordinate maxx+idelta,0
+ * where maxx is the largest positive x excursion of the
+ * plotter since the last call to mpage.
+ */
+
+void
+mpage(int idelta)
+{
+ iplot(0, maxx + idelta, 0);
+ xyres();
+}
+
+void
+setchsize(int n)
+{ /* set character size */
+ switch (n) {
+ case 4:
+ esc(';');
+ break;
+ case 3:
+ esc(':');
+ break;
+ case 2:
+ esc('9');
+ break;
+ default:
+ esc('8');
+ break;
+ }
+}
+
+void
+setzw(int n)
+{ /* set beam and vector mode */
+ esc(n);
+}
diff --git a/tekplot.h b/tekplot.h
new file mode 100644
index 0000000..107ffb2
--- /dev/null
+++ b/tekplot.h
@@ -0,0 +1,45 @@
+/* $Id$ */
+
+#ifndef _TEKPLOT_H
+#define _TEKPLOT_H
+
+/* arguments to setzw() */
+#define TEKNZNV 96 /* Normal Z axis and Normal vectors */
+#define TEKNZDOT 97 /* Normal Z dotted vectors */
+#define TEKNZDOTDASH 98 /* Normal Z dot-dash vectors */
+#define TEKNZSHORTDASH 99 /* short dash */
+#define TEKNZLONGDASH 100 /* long dash */
+#define TEKWZNV 112 /* Write-thru, Normal vectors */
+#define TEKWZDOT 113 /* Write-thru, Dotted vectors */
+#define TEKDZNV 108 /* Defocused, Normal vectors */
+
+__BEGIN_DECLS
+
+void iplot(int, int, int); /* i x y */
+void alpha(void);
+void page(void);
+void setzw(int);
+int kurse(int *, int *, int *); /* char x y */
+
+void esc(char);
+void xycvt(int, int);
+void alpha(void);
+void inittek(void);
+void endtek(void);
+void page(void);
+void disp(char *,...);
+void spad(char *,...);
+void dispii(char *, int *);
+void spadii(char *, int *);
+void spadiid(char *, int *);
+void xyplot(int, int, int);
+void xymove(int, int);
+void mech(int);
+void xyres(void);
+void mpage(int);
+void setchsize(int);
+void setzw(int);
+
+__END_DECLS
+
+#endif