/* xvbidebug.c * by Nathan Laredo (laredo@gnu.org) */ #define DATA_FROM_FILE #define PREFILTER_DATA 2 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include Display *mydisplay; Window mywindow; GC mygc; GC mygc2; XGCValues gcvals; XEvent myevent; int myscreen; XSizeHints myhint; KeySym mykey; XColor mycolor; XFontStruct *font_struct; unsigned long myforeground, mybackground; XWindowAttributes attribs; /* for vis, depth, width, height */ XSetWindowAttributes myattribs; /* for window creation */ XPoint vbipoints[1600]; /* for drawing data */ long myevents; /* keep track of our events */ char title[4096]; /* window title */ unsigned char vbibuf[65536]; char marquee[101]; char *ccode = " !\"#$%&'()a+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[e]iouabcdefghijklmnopqrstuvwxyzc/Nn."; /* this is NOT exactly right */ char outbuf[2048]; int parityok(int n) { /* check parity for 2 bytes packed in n */ #if 1 return 1; #else int j, k; for (k = 0, j = 0; j < 7; j++) if (n & (1 << j)) k++; if ((k & 1) && (n && 0x80)) return 0; for (k = 0, j = 8; j < 15; j++) if (n & (1 << j)) k++; if ((k & 1) && (n && 0x8000)) return 0; return 1; #endif } #ifdef PREFILTER_DATA #define NOISE 8 #else #define NOISE 45 #endif int decodebit(unsigned char *data, int threshold) { int i, sum = 0; for (i = 0; i < 32; i++) sum += data[i]; return (sum > (threshold << 5)); } int maxpos[7] = {200, 260, 320, 380, 440, 500, 600}; int ccdecode(unsigned char *vbiline) { int max[7], min[7], val[7], i, clk, tmp, sample, packedbits = 0; for (clk = 0; clk < 7; clk++) max[clk] = min[clk] = val[clk] = -1; clk = tmp = 0; i = 10; while (clk < 7 && i < maxpos[clk]) { /* find and lock all 7 clocks */ sample = vbiline[i]; if (max[clk] < 0) { /* find maximum value before drop */ if (sample > 50 && sample > val[clk]) (val[clk] = sample, tmp = i); /* mark new maximum found */ else if (val[clk]-sample>NOISE) { /* far enough */ XDrawLine(mydisplay, mywindow, mygc, tmp>>1, 30, tmp>>1, 128); max[clk] = tmp; i = tmp + 16; if (clk) { tmp -= max[clk - 1]; sprintf(title, "%d", tmp); XDrawString(mydisplay, mywindow, mygc, min[clk - 1]>>1, 50, title, strlen(title)); if (tmp < 42 || tmp > 84) return 0; /* wrong frequency clock */ } } } else { /* find minimum value after drop */ if (!clk && sample > vbiline[max[0]]) { max[0] = -1; /* mistake on first data */ continue; } if (sample < val[clk]) (val[clk] = sample, tmp = i); /* mark new minimum found */ else if (sample-val[clk]>NOISE) { /* searched far enough */ if (clk < 6) XDrawLine(mydisplay, mywindow, mygc, tmp>>1, 226, tmp>>1, 256); min[clk++] = tmp; i = tmp + 16; } } i++; } if (clk != 7) /* failure to locate clock lead-in */ return 0; /* calculate threshold */ sample = (vbiline[max[6]] + vbiline[min[6]]) >> 1; /* found clock lead-in, double-check start */ i = max[6] + 144; if (!decodebit(&vbiline[i], sample)) return 0; XDrawLine(mydisplay, mywindow, mygc, i>>1, 30, i>>1, 256); tmp = i + 57; /* tmp = data bit zero */ for (i = 0; i < 16; i++) { clk = tmp + i * 57; if (decodebit(&vbiline[clk], sample)) { XDrawLine(mydisplay, mywindow, mygc, clk>>1, 30, clk>>1, 256 - sample); packedbits |= 1 << i; } else XDrawLine(mydisplay, mywindow, mygc, clk>>1, 256 - sample, clk>>1, 256); } if (parityok(packedbits)) return packedbits; return 0; } /* ccdecode */ void ProcessLine(unsigned char *s) { int w1, b1, b2; static lastchar = 0, mode = 0; static nocc = 0; int m, n; m = strlen(outbuf); w1 = ccdecode(s); if (!w1) nocc++; sprintf(title, "%d", nocc); XDrawString(mydisplay, mywindow, mygc, 20, 245, title, strlen(title)); b1 = w1 & 0x7f; b2 = (w1 >> 8) & 0x7f; if ((b1 & 96)) { if (b1 > 31) { strncat(outbuf, &ccode[b1 - 32], 1); if (lastchar == '.' || lastchar == '[' || lastchar == '>' || lastchar == ']' || lastchar == '!' || lastchar == '?') outbuf[strlen(outbuf) - 1] = toupper(ccode[b1 - 32]); if (b1 > 32) lastchar = ccode[b1 - 32]; } if (b2 > 31) { strncat(outbuf, &ccode[b2 - 32], 1); if (lastchar == '.' || lastchar == '[' || lastchar == '>' || lastchar == ']' || lastchar == '!' || lastchar == '?') outbuf[strlen(outbuf) - 1] = toupper(ccode[b2 - 32]); if (b2 > 32) lastchar = ccode[b2 - 32]; } } if (!(b1 & 96) && b1 && *outbuf) if (outbuf[strlen(outbuf) - 1] != ' ') strncat(outbuf, ccode, 1); n = strlen(outbuf); if (n - m > 0) { memcpy(marquee, &marquee[n - m], 100 - (n - m)); strncpy(&marquee[100 - (n - m)], &outbuf[m], n-m); } if (!(b1 & 96) && b1 && *outbuf) { if (++mode > 4) { fprintf(stderr, "%s\n", outbuf); *outbuf = 0; mode = 0; } } } /* ProcessLine */ void init_display(int argc, char **argv) { if (!getenv("DISPLAY")) { fprintf(stderr, "DISPLAY not set.\n"); exit(1); } if (!(mydisplay = XOpenDisplay(getenv("DISPLAY")))) { fprintf(stderr, "Unable to open display.\n"); exit(1); } mybackground = BlackPixel(mydisplay, myscreen); myforeground = WhitePixel(mydisplay, myscreen); myhint.width = 800; myhint.height = 256; myhint.max_width = 800; myhint.max_height = 256; myhint.min_width = 800; myhint.min_width = 256; myhint.x = 0; myhint.y = 580; /* to add aspect ratio restriction, add to mask below */ myhint.flags = PSize | PMinSize | PMaxSize | PPosition; myevents = myattribs.event_mask = KeyPressMask | ButtonPressMask; myattribs.background_pixel = mybackground; mywindow = XCreateWindow(mydisplay, DefaultRootWindow(mydisplay), 0, 0, myhint.width, myhint.height, 0, attribs.depth, InputOutput, attribs.visual, CWEventMask | CWBackPixel, &myattribs); sprintf(title, "xvbidebug 11"); XSetStandardProperties(mydisplay, mywindow, title, title, None, argv, argc, &myhint); gcvals.foreground = myforeground; gcvals.background = mybackground; mygc = XCreateGC(mydisplay, mywindow, GCForeground | GCBackground, &gcvals); mycolor.flags = DoRed | DoGreen | DoBlue; mycolor.red = 32767; mycolor.green = 49152; mycolor.blue = 65535; mycolor.pad = 0; XAllocColor(mydisplay, DefaultColormap(mydisplay, myscreen), &mycolor); gcvals.foreground = mycolor.pixel; mygc2 = XCreateGC(mydisplay, mywindow, GCForeground | GCBackground, &gcvals); XMapRaised(mydisplay, mywindow); } int main(int argc, char **argv) { fd_set rdfs; int vbifd, xfd, done = 0, i, j = 22528, k, m; unsigned int *vbicount, oldcount = 0, dropcount = 0; #ifdef DATA_FROM_FILE if ((vbifd = open("/home/ftp/vbidata", O_RDONLY)) < 0) { perror("open /dev/vbi"); exit(1); } #else if ((vbifd = open("/dev/vbi", O_RDONLY)) < 0) { perror("open /dev/vbi"); exit(1); } #endif init_display(argc, argv); for (i=0; i<100; i++) marquee[i] = ' '; marquee[i] = 0; xfd = ConnectionNumber(mydisplay); for (i = 0; i < 1600; i++) vbipoints[i].x = i / 2; /* Main event loop */ while (!done) { FD_ZERO(&rdfs); FD_SET(xfd, &rdfs); FD_SET(vbifd, &rdfs); select(FD_SETSIZE, &rdfs, NULL, NULL, NULL); if (FD_ISSET(xfd, &rdfs)) while (XPending(mydisplay)) { XNextEvent(mydisplay, &myevent); j += 2048; if (j >= 65536) j = 0; sprintf(title, "xvbidebug %d", j >> 11); XStoreName(mydisplay, mywindow, title); } if (FD_ISSET(vbifd, &rdfs)) { read(vbifd, vbibuf, 65536); #ifdef DATA_FROM_FILE sleep(1); /* pass through data slowly for close observation */ #endif vbicount = (unsigned int *) &vbibuf[65532]; if (oldcount && oldcount + 1 != *vbicount) { dropcount += (*vbicount - oldcount); } oldcount = *vbicount; XClearWindow(mydisplay, mywindow); sprintf(title, "%d %d %s", dropcount, *vbicount, marquee); #ifdef PREFILTER_DATA for (i = 0; i < 1600; i++) vbipoints[i].y = 256 - vbibuf[i + j]; for (m = 0; m < PREFILTER_DATA; m++) if (m & 1) for (i = 3; i < 1600; i++) { k = vbibuf[i + j - 3] + vbibuf[i + j - 2] + vbibuf[i + j - 1] + vbibuf[i + j] + vbibuf[i + j + 1] + vbibuf[i + j + 2] + vbibuf[i + j + 3] + vbibuf[i + j + 4]; k >>= 3; vbibuf[i + j - 3] = vbibuf[i + j - 2] = vbibuf[i + j - 1] = vbibuf[i + j] = vbibuf[i + j + 1] = vbibuf[i + j + 2] = vbibuf[i + j + 3] = vbibuf[i + j + 4] = k; } else for (i = 1597; i > 3; i--) { k = vbibuf[i + j - 3] + vbibuf[i + j - 2] + vbibuf[i + j - 1] + vbibuf[i + j] + vbibuf[i + j + 1] + vbibuf[i + j + 2] + vbibuf[i + j + 3] + vbibuf[i + j + 4]; k >>= 3; vbibuf[i + j - 3] = vbibuf[i + j - 2] = vbibuf[i + j - 1] = vbibuf[i + j] = vbibuf[i + j + 1] = vbibuf[i + j + 2] = vbibuf[i + j + 3] = vbibuf[i + j + 4] = k; } XDrawPoints(mydisplay, mywindow, mygc2, vbipoints, 1600, CoordModeOrigin); #endif for (i = 0; i < 1600; i++) vbipoints[i].y = 256 - vbibuf[i + j]; XDrawString(mydisplay, mywindow, mygc, 20, 20, title, strlen(title)); XDrawLines(mydisplay, mywindow, mygc, vbipoints, 1600, CoordModeOrigin); ProcessLine(&vbibuf[j]); XFlush(mydisplay); } } /* while */ close(vbifd); XFreeGC(mydisplay, mygc); XDestroyWindow(mydisplay, mywindow); XCloseDisplay(mydisplay); exit(0); } /* main */