Subject: C hires code for ATARI 1040 ST (fwd)

From: [email-masked] (John D Beutel)
Date: Mon, 7 Oct 91 12:43:19 EDT

HIRES HIRES HIRES HIRES HIRES HIRES HIRES HIRES HIRES HIRES

This is it, folks!  I can't believe it.

It really works.  I didn't do any of its development, but I have
tested it with Sozoban C (with minor adjustments--changing "tos.h"
to "osbind.h", and deleting two void's in forward function declarations).

Manfredo has tried posting it to the glove-list, but it's disappeared
into some black hole somewhere, so he asked me to post it for him.

I've gotten the data packets in the right sequence, but not the
right order.  They've started with Z and ended with A0 X Y,
so I don't have it all figured out yet, but that doesn't really
matter since even if the data packet is out of order, I can still
tell which byte is which by seeing where A0, 0, 0, 3F, FF, FF occur.

The problem with this program is that it uses busy loops for
very long times (i.e., over 75,000 microseconds).  That makes
the sample rate a little slow (which is okay since my ST can't
do much per second anyway), and---most importantly---it hogs
all the CPU time.  I'm working on a modification which uses the
MFP's timer A to generate an interrupt after the appropriate
long interval (D2SLOW) and then handle the rest of the protocol
in an ISR.  That should free up the CPU for graphics.  
I'll post it when I get it working. 

I'll also put this source in karazm.math.uh.edu:pub/incoming/VR
tonite when the anonymous ftp is allowed (Eric...).
If anyone has special questions about how the ST works,
for converting this code to other computers, I'll be happy to
see what answers I can dig up.

Now, does anyone have freely--distributable source for a nice
3D graphics library (PHIGS, maybe?), before I go write my own?...

Forwarded message:
> From [email-masked] Wed Oct  2 12:12:02 1991
> From: [email-masked] (Manfred Krauss)
> Message-Id: <[email-masked]>
> Subject: C hires code for ATARI 1040 ST
> To: jdb9608@rit
> Date: Wed, 2 Oct 91 17:22:37 MET
> X-Mailer: ELM [version 2.3 PL6]
> 
> Hi,
> 
> Following C program switches the glove into hi-res mode.
> The protocol goes via latch. The code works very well.
> 
> Next project is to build a little controller with a 68HC11 
> processor to connect the glove to any? computer via RS232
> interface. I've no experience in programming such a processor.
> Is anyone out there who is familiar with the 68HC11?
> I can send a complete timing diagramm and support the work
> with my knowledge.
> 
> Waiting for hints and comments.
> 
> manfredo
> 
> -------------------- cut here --------------------------------------
/**********************************************************************
 
    power.c       (c) manfredo 9/91           enjoy "HiRes" mode
 
                   [email-masked]
 
 	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.

	connect NINTENDO POWERGLOVE to ATARI 1040ST parallel port

	PG                          ATARI 

	+5V pin7                                          power supply +5V

	GND pin1                    pin18 parallel port & power supply GND

	data pin4                   pin1  parallel port

 	latch pin3                  pin2  parallel port

	clock pin2                  pin3  parallel port

    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

**********************************************************************/
	
#include <stdio.h>
#include <tos.h>

/* PSG (Programable Sound Generator) */
#define		PSG             0xff8800 /* sound chip read data */
#define		PSGW            0xff8802 /* sound chip write data */

/* registers in PSG */
#define		CONREG          7       /* read/write control reg */
#define		AREG            14      /* port A */
#define		BREG            15      /* port B */

/* read / write bits in PSG register 7 */
#define		AREAD           0xbf    /* A read bit in register 7 */
#define		BREAD           0x7f    /* B read bit in register 7 */
#define		AWRITE          0x40    /* A write bit in register 7 */
#define		BWRITE          0x80    /* B write bit in register 7 */

/* bits from parallel port */
#define		GDATA           0x20    /* Strobe (Pin 1) PG data in */
#define		GLATCH          0x01    /* bit1 (pin2) PG latch out */
#define		GCLOCK          0x02    /* bit2 (pin3) PG clock out */
#define		GCLOLAT         0x03    /* bit2  + bit 1 */

/* Delay timing */
#define		delay(val)     { \
                                register unsigned long i = val /7; \
                                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()       *wr = 0        /* clock 0 latch 0 */
#define     C0L1()       *wr = GLATCH   /* clock 0 latch 1 */
#define     C1L0()       *wr = GCLOCK   /* clock 1 latch 0 */
#define     C1L1()       *wr = GCLOLAT  /* clock 1 latch 1 */

#define     setporta()   *rd = CONREG; \
                         *wr = *rd & AREAD; \
                         *rd = AREG

#define     setportb()   *rd = CONREG; \
                         *wr = *rd | BWRITE; \
                         *rd = BREG

void Hires (void);
unsigned char getbyte (void);

void main ()
{
	long lola;
	unsigned char buf[12];
	register unsigned char *bp;

	lola = Super (0L); /* set supervisor mode to access hardware
	                      directly */
	printf ("lola <0x%x>\n", lola);  /* satisfy TC compiler */                                                
	
	Hires (); /* set PG into 'hires' mode */

	for ( ; ; ) /* read 12 byte packets */
	{
		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);

		printf ("Glove %-2x %-2x %-2x %-2x %-2x %-2x %-2x %-2x %-2x %-2x %-2x %-2x\n",
				buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
				buf[6], buf[7], buf[8], buf[9], buf[10], buf[11]);
	}
}

unsigned char getbyte ()
{
	register unsigned char *rd = (unsigned char *)PSG;
	register unsigned char *wr = (unsigned char *)PSGW;
	register int i;
	register unsigned Glov = 0;	

	/* prepare port b as output port */
	setportb ();

        /* generate a reset (latch) pulse */
	C1L0 ();
	C1L1 ();
	for (i = 1; i-- > 0; ); /* 5 us delay */
	C1L0 ();

	/* configure port a as input */
	setporta ();

	/* read a bit */
	*rd &= GDATA;
	Glov <<= 1;
	Glov += *rd >> 7;

	/* prepare port b as output port */
	setportb ();

	/* generate a clock pulse */
	C0L0 ();
	C1L0 ();
	
	/* configure port a as input */
	setporta ();

	/* read a bit */
	*rd &= GDATA;
	Glov <<= 1;
	Glov += *rd >> 7;

	/* prepare port b as output port */
	setportb ();

	/* generate a clock pulse */
	C0L0 ();
	C1L0 ();
	
	/* configure port a as input */
	setporta ();

	/* read a bit */
	*rd &= GDATA;
	Glov <<= 1;
	Glov += *rd >> 7;

	/* prepare port b as output port */
	setportb ();

	/* generate a clock pulse */
	C0L0 ();
	C1L0 ();
	
	/* configure port a as input */
	setporta ();

	/* read a bit */
	*rd &= GDATA;
	Glov <<= 1;
	Glov += *rd >> 7;

	/* prepare port b as output port */
	setportb ();

	/* generate a clock pulse */
	C0L0 ();
	C1L0 ();
	
	/* configure port a as input */
	setporta ();

	/* read a bit */
	*rd &= GDATA;
	Glov <<= 1;
	Glov += *rd >> 7;

	/* prepare port b as output port */
	setportb ();

	/* generate a clock pulse */
	C0L0 ();
	C1L0 ();
	
	/* configure port a as input */
	setporta ();

	/* read a bit */
	*rd &= GDATA;
	Glov <<= 1;
	Glov += *rd >> 7;

	/* prepare port b as output port */
	setportb ();

	/* generate a clock pulse */
	C0L0 ();
	C1L0 ();
	
	/* configure port a as input */
	setporta ();

	/* read a bit */
	*rd &= GDATA;
	Glov <<= 1;
	Glov += *rd >> 7;

	/* prepare port b as output port */
	setportb ();

	/* generate a clock pulse */
	C0L0 ();
	C1L0 ();
	
	/* configure port a as input */
	setporta ();

	/* read a bit */
	*rd &= GDATA;
	Glov <<= 1;
	Glov += *rd >> 7;

	/* prepare port b as output port */
	setportb ();

	/* generate a clock pulse */
	C0L0 ();
	C1L0 ();

	return Glov;  /* return the byte */
}

void Hires ()
{
	register unsigned char *rd = (unsigned char *)PSG;
	register unsigned char *wr = (unsigned char *)PSGW;
	register unsigned char Glov = 0;
	register int i;

	/* read 4 bits from glove */
	setportb ();

        /* generate a reset (latch) pulse */
	C1L0 ();
	C1L1 ();
	for (i = 1; i-- > 0; );   /* 5 us delay */
	C1L0 ();

	/* configure port a as input */
	setporta ();

	/* read a bit */
	*rd &= GDATA;
	Glov <<= 1;
	Glov += *rd >> 7;

	/* prepare port b as output port */
	setportb ();

	/* generate a clock pulse */
	C0L0 ();
	C1L0 ();
	
	/* configure port a as input */
	setporta ();

	/* read a bit */
	*rd &= GDATA;
	Glov <<= 1;
	Glov += *rd >> 7;

	/* prepare port b as output port */
	setportb ();

	/* generate a clock pulse */
	C0L0 ();
	C1L0 ();
	
	/* configure port a as input */
	setporta ();

	/* read a bit */
	*rd &= GDATA;
	Glov <<= 1;
	Glov += *rd >> 7;

	/* prepare port b as output port */
	setportb ();

	/* generate a clock pulse */
	C0L0 ();
	C1L0 ();
	
	/* configure port a as input */
	setporta ();

	/* read a bit */
	*rd &= GDATA;
	Glov <<= 1;
	Glov += *rd >> 7;

	/* prepare port b as output port */
	setportb ();

	/* generate a clock pulse */
	C0L0 ();
	C1L0 ();
	
	/* end of read 4 bits */

	/* prepare port b as output port */
	setportb ();

	C1L0 ();
	delay (16950);  /* 7212 us delay */

	setportb ();

	C1L1 ();
	delay (4750);   /* 2260 us delay */

	/* prepare port b as output port */
	setportb ();

	C1L0 ();	/* Start of 1. Byte */
	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);
	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);	

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C1L1 ();
	C0L1 ();
	C1L1 ();
	delay (D2BITS);
	
	/* prepare port b as output port */
	setportb ();

	C0L1 ();
	C1L1 ();
	delay (D2BITS);	

	/* prepare port b as output port */
	setportb ();

	C1L0 ();
	C0L0 ();
	C1L0 ();
	delay (D2BYTES);		

	/* prepare port b as output port */
	setportb ();

	C1L1 ();	/* Start of 2. Byte */
	C0L1 ();
	C1L1 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L1 ();
	C1L1 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C1L0 ();
	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C1L1 ();
	C0L1 ();
	C1L1 ();
	delay (D2BYTES);

	/* prepare port b as output port */
	setportb ();

	C1L0 ();	/* Start of 3. Byte */
	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);	

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);	

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);	

	/* prepare port b as output port */
	setportb ();

	C1L1 ();
	C0L1 ();
	C1L1 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C1L0 ();
	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BYTES);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();	/* start of 4. byte */
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BYTES);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();	/* start of 5. byte */
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C1L1 ();
	C0L1 ();
	C1L1 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C1L0 ();
	C0L0 ();
	C1L0 ();
	delay (D2BYTES);

	/* prepare port b as output port */
	setportb ();

	C1L1 ();	/* start of 6. byte */
	C0L1 ();
	C1L1 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L1 ();
	C1L1 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L1 ();
	C1L1 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L1 ();
	C1L1 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L1 ();
	C1L1 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L1 ();
	C1L1 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L1 ();
	C1L1 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L1 ();
	C1L1 ();
	delay (D2BYTES);

	/* prepare port b as output port */
	setportb ();

	C1L0 ();	/* start of 7. byte */
	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C0L0 ();
	C1L0 ();
	delay (D2BITS);

	/* prepare port b as output port */
	setportb ();

	C1L1 ();
	C0L1 ();
	C1L1 ();
	delay (1090); /* 892 us delay (end of 7. byte) */

	/* prepare port b as output port */
	setportb ();

	C1L0 ();
	delay (60000);   /* some time for the glove controller
						to relax */
}
-------------------- cut here --------------------------------------
----------------------------------------------------------------- 
Manfred Krauss,                     [email-masked]
Dept of Computer Science,
Technical University of Berlin,
Franklinstr. 28-29,
W-1000 Berlin 10,
Sekr. FR3-3,
Germany
----------------------------------------------------------------- 

--
J. David Beutel  11011011  [email-masked]  "I am, therefore I am."

---

From: Jay A. Carlson <[email-masked]>
Date: Mon, 7 Oct 91 16:42:29 CDT

I have a fair amount of HC11 experience.  I'm interested in doing the
powerglove interpreter---but I don't have a glove any more. :-(
I can look over code, and suggest design and strategies, however.  If
someone is doing the HC11 interpreter project, I'd love to provide
support.

  // Jay Carlson
\X/  [email-masked]

To subscribe to the MC68HC11 list, email to [email-masked].