/*-=-=-=-=-=-=-=-=-=-=-=- RCCL/RCI Notice of Copyright -=-=-=-=-=-=-=-=-=-=-*
 *									    *
 *	Copyright (C) 1987, 1991 by John E. Lloyd and Vincent Hayward.	    *
 *									    *
 *	Information on copyright permissions, as well as a complete	    *
 *	disclaimer of warranty, is given in the file COPYRIGHT.		    *
 *									    *
 *-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=*/

#include "sys.h"
#include "sensorIO.h"

#define VERBOSE	1

/* ----- Generic serial line unit procedures ------ */

typedef struct {
	SLU *si_unit;
  	char *si_rbuf;
	int si_rsize;
	char *si_wbuf;
	int si_wsize;
	int si_active;
  } SLUINFO;

static SLUINFO *sluinfo = 0;
extern int numSlu;
extern SLU_DESC sluDesc[];

configSlu ()
{
	int k;

	sluinfo = (SLUINFO*)getmem(numSlu*sizeof(SLUINFO));
	for (k=0; k<numSlu; k++)
	 { sluinfo[k].si_unit = sluGet(sluDesc[k].sl_dev);
	   sluinfo[k].si_rbuf = (char*)getmem(sluDesc[k].sl_rsize);
	   sluinfo[k].si_rsize = sluDesc[k].sl_rsize;
	   sluinfo[k].si_wbuf = (char*)getmem(sluDesc[k].sl_wsize);
	   sluinfo[k].si_wsize = sluDesc[k].sl_wsize;
	   sluinfo[k].si_active = 0;
	 }
}

getSlu (j, buf)
short j;
char *buf;
{
	register int k;
	int count;
	SLUINFO *slui;

	slui = &sluinfo[j];

	if (count = sluRcount (slui->si_unit))
	 { char *inputbuf = slui->si_rbuf;
	   for (k=0; k<count; k++)
	    { buf[k] = inputbuf[k];
	    }
	 }
	if (slui->si_active)
	 { sluRead (slui->si_unit, slui->si_rbuf, slui->si_rsize);
	 }
	return (count);
}

putSlu (j, buf, size)
short j, size;
char *buf;
{
	char output[256];

	strncpy (output, buf, size);
 	output[size] = '\0';
#if VERBOSE
	printf ("%% putting \"%s\" to SLU %d\n", output, j);
#endif
}

sluStart (chan)
short chan;
{
	sluOn (sluinfo[chan].si_unit);
#if VERBOSE
	printf ("%% turning slu %d on\n", chan);
#endif
}

sluStop (chan)
short chan;
{
	sluOff (sluinfo[chan].si_unit);	
#if VERBOSE
	printf ("%% turning slu %d off\n", chan);
#endif
}

/* ----- Generic digital to analog converter routine ----- */

extern short *DACAddr[];		/* Robot specific address info */
extern int numDAC;

/* These definitions assume a two's complement DAC register */
#define NUM_DAC_BITS	12
#define DAC_MAX		((1<<(NUM_DAC_BITS-1))-1)
#define DAC_MIN		(~DAC_MAX)

putDAC (j, value)
short j, value;
{
	if (0 <= j && j < numDAC)
	 { if (value > DAC_MAX)
	    { value = DAC_MAX;
	    }
	   else if (value < DAC_MIN)
	    { value = DAC_MIN;
	    }
	   *DACAddr[j] = value;
#if VERBOSE
	printf ("%% putting 0x%x to DAC %d\n", value, j);
	 }
#endif
}

/* ----- Generic parallel port access routines ----- */

extern unsigned short *pioOutAddr[];	/* Robot specific address info */
extern int numPioOut;
extern unsigned short *pioInAddr[];
extern int numPioIn;

putPio (j, value)
int j;
unsigned short value;
{
	unsigned short mask;

	extern int powerChan;
	extern int powerBit;
	extern int traceBit;

	if (j == powerChan)
	 { mask = (powerBit|traceBit);
	   value = (value & ~mask) | (mask & *pioOutAddr[j]);
	 }
	*pioOutAddr[j] = value;
}

unsigned short getPioIn (j)
int j;
{
	return (*pioInAddr[j]);
}

unsigned short getPioOut (j)
int j;
{
	return (*pioOutAddr[j]);
}
