/**********************************************************************
 
    power.c       (c) manfredo 9/91           enjoy "HiRes" mode
 
                   manfredo@opal.cs.tu-berlin.de
 
 	This program is without any WARRANTY use at your OWN risk
        @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
 
	The code is very ugly, but it was the only way to get speed
	on this poor hardware in C. It was developed on an ATARI
        1040ST with TC 1.1 using a logic analyzer to get the correct
	timings.
 
 
    Datapacket: (12 bytes)
 
    1.    2.    3.    4.    5.    6.    7.    8.    9.    10.   11.    12.
 
    A0    X     Y     Z    rot  finger  keys  00    00    3F    FF     FF
 
 
**********************************************************************/
 
/*********************************************************************
		      ported to PC compatibles by
			     Greg Alt 10/91
 
			    galt@peruvian.utah.edu
			 or galt@es.dsd.com
 
 
	I made the code a little less "ugly".  Also, the constants N & D
	should be tweeked to fit your system.  A 4/21 works for my 386/25,
	a 1/7 worked for an Atari ST.  It should probably be in the range
	1/10-1/2.  Keep tweeking it until the output matches the above
	format and isn't very jittery...
 
	I compiled this successfully with Turbo C 2.0...
 
	To connect the glove to your PC, look at the July 1990 issue of
	BYTE magazine.
 
**********************************************************************/
#define         N  4     /* Tweek this value */
#define         D  21
 
#include <stdio.h>
 
/* bits from parallel port */
#define		GDATA           0x10    /* PG data in */
#define		GLATCH          0x02    /* PG latch out */
#define		GCLOCK          0x01    /* PG clock out */
#define		GCLOLAT         0x03    /* clock + latch */
 
 
/* Delay timing */
#define	    delay(val)  {register unsigned long i=N*(int)(val/D);for(;i-->0;);}
 
 
#define     D2BYTES      192      /* delay between 2 bytes   96 us */
#define     D2BITS       21       /* delay between 2 bits    22 us */
#define     D2SLOW       32000    /* 4 slow bytes in packet  14720 us */
 
#define     C0L0()       outportb(0x378, 0)        /* clock 0 latch 0 */
#define     C0L1()       outportb(0x378, GLATCH)   /* clock 0 latch 1 */
#define     C1L0()       outportb(0x378, GCLOCK)   /* clock 1 latch 0 */
#define     C1L1()       outportb(0x378, GCLOLAT)  /* clock 1 latch 1 */
 
#define     readbit(x)   rd=inportb(0x379); rd&=GDATA; x=x<<1; x+=rd>>4;
unsigned char getbyte (void);
 
 
void Hires (void);
void getglove (unsigned char *);
 
typedef struct _glove_data
    {
    signed char  dum0,x,y,z,rot,fingers,keys,dum7,dum8,dum9,dumA,dumB;
    } glove_data;
 
void main ()
{
	unsigned char buf[12];
	glove_data   *glov;
 
	glov=(glove_data *)buf;
	Hires (); /* set PG into 'hires' mode */
	while(1)
	{
	getglove(buf); /* read 12 byte packets */
	printf("Glove %-2x %-2x %-2x %-2x %-2x %-2x ",
	       buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]);
	printf(      "%-2x %-2x %-2x %-2x %-2x %-2x\n",
	       buf[6],buf[7],buf[8],buf[9],buf[10],buf[11]);
	}
}
 
 
void getglove(buf)      /* read 12 byte packets */
unsigned char *buf;
{
register unsigned char *bp;
 
bp = buf;
*bp++ = getbyte ();
delay (D2BYTES);
*bp++ = getbyte ();
delay (D2BYTES);
*bp++ = getbyte ();
delay (D2BYTES);
*bp++ = getbyte ();
delay (D2BYTES);
*bp++ = getbyte ();
delay (D2BYTES);
*bp++ = getbyte ();
delay (D2BYTES);
*bp++ = getbyte ();
delay (D2BYTES);
*bp++ = getbyte ();
delay (D2SLOW);
*bp++ = getbyte ();
delay (D2SLOW);
*bp++ = getbyte ();
delay (D2SLOW);
*bp++ = getbyte ();
delay (D2SLOW);
*bp++ = getbyte ();
delay (D2SLOW);
}
 
 
 
unsigned char getbyte ()
{
	register unsigned char rd;
	register int i;
	register unsigned char Glov = 0;
 
        /* generate a reset (latch) pulse */
	C1L0 ();
	C1L1 ();
	for (i = 1; i-- > 0; ); /* 5 us delay */
	C1L0 ();
	readbit(Glov);
	C0L0 (); C1L0 ();  /* pulse */
	readbit(Glov);
	C0L0 (); C1L0 ();  /* pulse */
	readbit(Glov);
	C0L0 (); C1L0 ();  /* pulse */
	readbit(Glov);
	C0L0 (); C1L0 ();  /* pulse */
	readbit(Glov);
	C0L0 (); C1L0 ();  /* pulse */
	readbit(Glov);
	C0L0 (); C1L0 ();  /* pulse */
	readbit(Glov);
	C0L0 (); C1L0 ();  /* pulse */
	readbit(Glov);
	C0L0 (); C1L0 ();  /* pulse */
	return Glov;  /* return the byte */
}
 
 
void Hires ()
{
	register unsigned char rd;
	register unsigned char Glov = 0;
	register int i;
 
	/* read 4 bits from glove */
 
        /* generate a reset (latch) pulse */
	C1L0 ();
	C1L1 ();
	for (i = 1; i-- > 0; );   /* 5 us delay */
	C1L0 ();
	readbit(Glov);
	C0L0 (); C1L0 ();    /* pulse clock */
	readbit(Glov);
	C0L0 (); C1L0 ();    /* pulse clock */
	readbit(Glov);
	C0L0 (); C1L0 ();    /* pulse clock */
	readbit(Glov);
	C0L0 (); C1L0 ();    /* pulse clock */
 
	/* end of read 4 bits */
 
	C1L0 ();
	delay (16950);  /* 7212 us delay */
 
	C1L1 ();
	delay (4750);   /* 2260 us delay */
 
	C1L0 ();	/* Start of 1. Byte */
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C1L1 ();	C0L1 ();	C1L1 ();	delay (D2BITS);
	C0L1 ();	C1L1 ();	delay (D2BITS);
	C1L0 ();	C0L0 ();	C1L0 ();	delay (D2BYTES);
 
	C1L1 ();	/* Start of 2. Byte */
	C0L1 ();	C1L1 ();	delay (D2BITS);
	C0L1 ();	C1L1 ();	delay (D2BITS);
	C1L0 ();	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C1L1 ();	C0L1 ();	C1L1 ();	delay (D2BYTES);
 
	C1L0 ();	/* Start of 3. Byte */
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
       	C1L1 ();	C0L1 ();	C1L1 ();	delay (D2BITS);
	C1L0 ();	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BYTES);
 
			/* start of 4. byte */
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
        C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BYTES);
 
			/* start of 5. byte */
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C1L1 ();	C0L1 ();	C1L1 ();	delay (D2BITS);
	C1L0 ();	C0L0 ();	C1L0 ();	delay (D2BYTES);
 
	C1L1 ();	/* start of 6. byte */
	C0L1 ();	C1L1 ();	delay (D2BITS);
	C0L1 ();	C1L1 ();	delay (D2BITS);
	C0L1 ();	C1L1 ();	delay (D2BITS);
	C0L1 ();	C1L1 ();	delay (D2BITS);
	C0L1 ();	C1L1 ();	delay (D2BITS);
	C0L1 ();	C1L1 ();	delay (D2BITS);
	C0L1 ();	C1L1 ();	delay (D2BITS);
	C0L1 ();	C1L1 ();	delay (D2BYTES);
 
	C1L0 ();	/* start of 7. byte */
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C0L0 ();	C1L0 ();	delay (D2BITS);
	C1L1 ();	C0L1 ();	C1L1 ();	delay (1090);
			/* 892 us delay (end of 7. byte) */
 
	C1L0 ();
	delay (60000);   /* some time for the glove controller to relax */
 
}
 
