From 846de8d8d55fb0b5b20e9743d20f77c21b029f1f Mon Sep 17 00:00:00 2001 From: Dimitri Sokolyuk Date: Thu, 25 Aug 2011 08:55:47 +0000 Subject: Tek ILDA --- Makefile | 11 ++ tekilda.c | 305 ++++++++++++++++++++++++++++++++++++++ tekplot.c | 496 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ tekplot.h | 45 ++++++ 4 files changed, 857 insertions(+) create mode 100644 Makefile create mode 100644 tekilda.c create mode 100644 tekplot.c create mode 100644 tekplot.h 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 + * + * 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 /* endian conversion */ +#include /* endian conversion */ +#include +#include +#include +#include +#include +#include +#include +#include +#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 +#include +#include +#include +#include +#include +#include +#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 -- cgit v1.2.3