/*
 * Quick and dirty logic analyzer
 *
 * Permission to use, copy, and distribute this software and its
 * documentation for any purpose and without fee is hereby granted,
 * provided that the above copyright notice appear in all copies and that
 * both that copyright notice and this permission notice appear in
 * supporting documentation.
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
 * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
 * MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 * TODO: 
 * Add arguments for specifying:
 * - Printer port
 * - Number of pulses
 * - Sampled time
 * - Trigger event (channel / value)
 * Use time measurements on x scale
 * Capture and display channels
 *
 * Requires the Linux inb(2) call and GNU Plot
 * Compile with -O and run as root.
 *
 * (C) Copyright 2003 Diomidis Spinellis
 */

#include <stdio.h>
#include <sys/io.h>

#define DATA 0x379

#define NSAMPLE (1024 * 1024)

struct {
	int t;			// time
	int v;			// value
} samples[NSAMPLE];

// Return true if a printer port bit is set
static int
portbit(void)
{

	return inb(DATA) != 0x78;
}

main(int argc, char *argv[])
{
	int init, b, count;
	int t = 0;
	int v = 0;
	int nsamples = 0;
	FILE *f;

	// Get I/O permission
	if (iopl(3) < 0) {
		perror("iopl");
		exit(1);
	}

	f = fopen("scope.gpl", "w");
	fprintf(f, "plot [] [-5:10] \"scope.dat\" with steps\npause -1\n");
	fclose(f);

	outb('\0', DATA);
	for (;;) {
		for (count = 0; (b = portbit()) == init; count++) {
			t++;
			if (count > 10000 && nsamples > 5) {
				int i;

				f = fopen("scope.dat", "w");
				for (i = 1; i < nsamples - 1; i++)
					fprintf(f, "%d %d\n", samples[i].t, samples[i].v);
				fclose(f);
				system("gnuplot -geometry +20+20 scope.gpl");
				nsamples = t = 0;
			}
		}

		if (nsamples > 0) {
			samples[nsamples].t = t;
			samples[nsamples].v = v ? 5 : 0;
		}
		v = !v;
		init = b;
		nsamples++;
	}
}

