BBN-V6/dmr/ar.c

#
/*  Driver for AR11.
 *	Device name: /dev/ar0
 *	Stty arguments to set sampling rate, number of channels,
 *		and unipolar/bipolar analog.
 *	Read A/D converted values (first word is sample number - unsigned
 *		integer value, with 16 bit wrap-around
 *	Write D/A values, "intensified" on loading of Y. If an odd number
 *		of words are written, trailing values will be ignored.
 */

#include "../h/param.h"
#include "../h/user.h"

#define AR	0170400

/* A/D status */
#define UNIPOLAR	020000
#define CHAN		07400
#define CHANONE 	00400
#define DONE		0200
#define IENABLE 	0100
#define OVENABLE	040
#define EXTENABLE	020
#define GO		01

/* Clock status */
#define EXTINPUT	0100000
#define EXTENABLE	040000
#define REPEAT		0400
#define OVERFL		0200
#define OVERENABLE	0100
#define ALWAYS		020	/* Always set for AR11 */
#define RATE		070
#define CLENABLE	01

#define YMODE		010	/* "intensify" on loading of Y */

struct
{	int vals[17];	/* vals[0] is sample number */
	int admode;
	char nchans;
	char arflags;
} ar_data;

struct
{	int adstat;
	int adbuf;
	int clkstat;
	int clkpre;
	int dispstat;
	int xbuffer;
	int ybuffer;
	int clkctr;
};

struct {char lobyte, hibyte;};

/* arflags */
#define OPEN	01

aropen(dev,flag)
int dev, flag;
{	/* Default rate is 0.  Until first stty call, return 0s on reads */
	int i;
	if (ar_data.arflags&OPEN)
		u.u_error = EACCES;
	else
	{	ar_data.arflags =| OPEN;
		for (i=17; i--;) ar_data.vals[i] = 0;
		AR->dispstat = YMODE;
	}
}

arclose(dev)
int dev;
{	ar_data.arflags = 0;
	AR->clkstat = AR->adstat = 0;
}

arsgtty(dev,v)
int dev, v;
/* Arguments are:
 * word       data
 *  1	Sampling period --
 *		hi byte is count, lo byte is minus exponent of clock rate
 *		(2 for 100 hz, 3 for 1khz, ..., 6 for 1mhz)
 *		Example: 5<<8 | 3  is 5 milliseconds between samples
 *  2	Lo byte is highest numbered channel to be sampled.
 *		Example: 3 to sample channels 0, 1, 2, and 3.
 *  2	Hi byte is non-zero if A/D range is unipolar (0-5 volts), zero if
 *		bipolar (-2.5 to 2.5 volts).
 *  3	Reserved
 * Note: The total number of samples per second must not exceed 20000, i.e.,
 *	the sampling period divided by the number of channels must be at least
 *	50 microseconds.  Also, the sampling period must be less than 2.56
 *	seconds.  If the given rate cannot be achieved, no sampling will
 *	occur.
 */
/*      Modified 7/18/75 to limit to 0.01 second period to reduce time
 *      consumable by AR11.
 */
{	register int n, m, t;
	int mm;
	if (v)
		u.u_error = EBADF;
	else
	{	ar_data.nchans = (u.u_arg[1]&017);
		if (n = (u.u_arg[0].hibyte & 0377))
		{	m = u.u_arg[0].lobyte&0377;
			while (n<=25)
			{	n =* 10;
				m++;
			}
			if (m<2) goto badtime;  /* 2.55 secs is max */
			/* Verify sufficient time per sample
			t = (100*n+ar_data.nchans)/(ar_data.nchans+1); */
			/* Multiply by 100 for precision */
			t = 100*n;
			mm = m;
			while (t<=25)
			{	t =* 10;
				mm++;
			}
			while (t>255)
			{       t =/ 10;
				mm--;
			}
			/* 25 < t <= 255, and time per sample is
			 *  t*10**(-mm-2)
			 */
		/*      if (mm>=5 || ((mm==4) && (t<50))) goto badtime; */
			if (mm>=4 || ((mm==3) && (t<200))) goto badtime;
			/* Make clock rate between 100hz and 1mhz */
			while (m<2)
			{	n =* 10;
				m++;
			}
			while ((n!=0) && (m>6))
			{	if ((n%10) != 0) goto badtime;
				n =/ 10;
				m--;
			}
		}
		else
badtime:	{	m = 7;
			u.u_error = EINVAL;
		}
		AR->clkpre = -n;
		AR->clkstat = (REPEAT|ALWAYS|CLENABLE) | ((7-m)<<1);
		AR->adstat = ar_data.admode =
			(u.u_arg[1].hibyte ? UNIPOLAR : 0) |
				(IENABLE|OVENABLE);
	}
}

arrint()        /* Runs at priority level 6 */
{	register int *vp, i;
	vp = ar_data.vals;
	(*vp++)++;
	AR->adstat =& ~(IENABLE|OVENABLE);
	*vp++ = AR->adbuf;
	for (i=  ar_data.nchans; i--;)
	{       AR->adstat =+ CHANONE;
		AR->adstat =| GO;
		while ((AR->adstat&DONE) == 0) ;
		*vp++ = AR->adbuf;
	}
	AR->adstat = ar_data.admode;
}

arread(dev)
int dev;
{       register char *vp, i;
	i = 34;  /* 16 channels + time */
	vp = ar_data.vals;
	spl6();
	while (i-- && passc(*vp++) == 0) ;
	spl0();
}

arwrite(dev)
int dev;
{	register int i, c;
	register char *cp;
	int xy[2];
	for (;;)
	{	cp = xy;
		for (i=4; i--;)
			if ( (c = cpass()) != -1)
				*cp++ = c;
			else
				break;
		AR->xbuffer = xy[0];
		AR->ybuffer = xy[1];
		return;
	}
}



arclint()	/* Clock interrupt.  (In case we ever use it.) */
{
}

ardsint()       /* Display interrupt (In case we ever use it.) */
{
}