/* Test DAC for stability etc */

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <errno.h>
#include <unistd.h>
#include <getopt.h>
#include <stdint.h>
#include <string.h>
#include <syslog.h>
#include <err.h>
#include <linux/serial.h>
#include <sys/signal.h>
#include <sys/time.h>
#include "serial-util.h"
#include "gpib.h"
#include "zoom.h"
#include <math.h>
#include "mt19937ar.h"

void write_random(int zoom, int gpib);

#define info(x...) fprintf(stderr,x)

int g_quit = 0;
void handle_sig(int sig) { g_quit = 1; }

int main(int argc, char *argv[])
{
	char *zoomdev=strdup("/dev/serial/by-id/usb-FTDI_"
                             "FT232R_USB_UART_A6007wc5-if00-port0");
	char *gpibdev=strdup("/dev/serial/by-id/usb-Prologix_"
                             "Prologix_GPIB-USB_Controller_PXQQY20G-if00-port0");
	int getopt_index;
	int zoom, gpib;
	unsigned long seed = 1337;

	static struct option long_opts[] = {
		{ "zoom-device", required_argument, NULL, 'Z' },
		{ "gpib-device", required_argument, NULL, 'G' },
		{ "seed", required_argument, NULL, 's' },
		{ "help", no_argument, NULL, 'h' },
		{ 0, 0, 0, 0}
	};
	int help=0;
	char c;

	while ((c = getopt_long(argc, argv, "Z:G:s:h?",
				long_opts, &getopt_index)) != -1) {
		switch(c)
		{
		case 'Z':
			free(zoomdev);
			zoomdev = strdup(optarg);
			break;
		case 'G':
			free(gpibdev);
			gpibdev = strdup(optarg);
			break;
		case 's':
			seed = atol(optarg);
			if(seed == 0)
				errx(1, "invalid seed: %s", optarg);
			break;
		case 'h':
		case '?':
		default:
			help = 1;
			break;
		}
	}

	if (help) {
		fprintf(stderr, "Zoom Nilm DC Test\n");
		fprintf(stderr, "usage: %s [options]\n\n", *argv);
		fprintf(stderr, "  -Z,  --zoom-device %-14s "
                        "zoom NILM serial port\n", "/dev/xxx" /*zoomdev*/);
		fprintf(stderr, "  -G,  --gpib-device %-14s "
                        "GPIB serial port\n", "/dev/xxx" /*gpibdev*/);
		fprintf(stderr, "  -s,  --seed %-16ld random seed\n", seed);
		fprintf(stderr, "  -h,  --help                       "
                        "this help\n");
		return 1;
	}

	signal(SIGINT, handle_sig);

	info("Initializing twister with seed %ld\n", seed);
	init_genrand(seed);

	info("Opening Zoom NILM device %s\n", zoomdev);
	if ((zoom = serial_open(zoomdev, 115200)) == -1)
		err(1, "failed to open zoom device %s", zoomdev);

	info("Opening GPIB device %s\n", gpibdev);
	if ((gpib = serial_open(gpibdev, 9600)) == -1)
		err(1, "failed to open gpib device %s", gpibdev);

	/* do it */
	write_random(zoom, gpib);

	close(zoom);
	close(gpib);
	return 0;
}

void write_random(int zoom, int gpib)
{
	int dac;
	double meas;
	struct timeval now;

	info("Initializing Zoom NILM\n");
	if (zoom_init_nozero(zoom) < 0) goto fail;

	info("Initializing GPIB\n");
	if (gpib_init(gpib) < 0) goto fail;

	info("Initializing Keithley\n");
	if (gpib_addr(gpib, 23) < 0) goto fail;
	if (keithley2002_init_volts(gpib) < 0) goto fail;
	if (isnan(keithley2002_read(gpib))) goto fail;

	info("Running\n");
	while (!g_quit) {
		dac = genrand_int32() & 0x3ff;
		zoom_write_dac(zoom, dac);
		gettimeofday(&now, NULL);
		meas = keithley2002_read(gpib);
		printf("%ld.%06ld %d %.12f\n", now.tv_sec, now.tv_usec,
                       dac, meas);
		fflush(stdout);
	}

safecleanup:
	return;

fail:
	info("Failed\n");
	goto safecleanup;
}

