#include <stdio.h>
#include <sys/plp.h>
#include <fcntl.h>
#include <unistd.h>

/*
 * Name	   : portdemo.c
 * Machines: IRIS 4D/30, 4D/35, 4D/RPC, 4D/RPC-50, Indy, Indigo2 and
 *           Challenge/Onyx. (only tested on an Indy so far).
 * Purpose : Demonstrate how to write to the parallel port.
 * Author  : James Ward
 * Contact : j.w.ward@dcs.hull.ac.uk
 *	         www.crema.co.uk
 * Date	   : 29/05/96 - Created.
 * Changes : 30/05/96 - Added more info to note 1, describing (roughly) what
 *			happens when you write to the rewired port. (JWW)
 *
 * Distribute freely, use at your own risk.
 * This setup has worked for several months on our Indy without any problems.
 *
 */

 
/* Notes:
 *	1. You can turn the parallel port into a simple eight-bit latched
 *	   output port (ie. eight TTL lines that you can control from software)
 *	   by simply wiring /STROBE (pin 1) to /ACKNOWLEDGE (pin 10), and
 *	   linking BUSY (pin 11) to GROUND (pins 19..25). Values written to the
 *	   port will then appear on D1..D8 (pins 2..9) and will remain there
 *	   until you write to the port again. Very useful for hardware projects!
 *	   See the plp man page for a full connector pinout.
 *
 *	   How this works:
 *		1. Indy wants to write data to the port, so it looks for the
 *		   BUSY signal. We have tied this low (ie. to ground) so that
 *		   the Indy never gets a BUSY signal and doesn't wait for one.
 *		2. The Indy places the data on pins D1..D8, then pulses /STROBE
 *		   low (it is normally high), to indicate that valid data is
 *		   available on D1..D8.
 *		3. Normally, the Indy would expect a /ACKNOWLEDGE signal but, 
 *		   since we have tied /ACKNOWLEDGE to /STROBE, the strobe signal
 *		   automatically acknowledges the transfer - we can write to the
 *		   port freely, without any delays.
 *
 *
 *      2. There are ioctls that allow you to alter read/write timeout and to
 *	   change the length of the strobe pulses that the port generates.
 *	   If you are using a simple setup like that described above, you
 *	   probably don't need to use the ioctls.
 *	   More details are available on the plp man page, and I have examples
 *	   of using these controls if you get stuck.
 *
 *	3. This program writes the values 0..9 to the parallel port, with a
 *	   short delay after each write. Here is what you should see (providing
 *	   you have some hardware plugged in to the port, or the port is
 *	   connected as described in note 1.
 
	    > cc -o portdemo portdemo.c			.... compile this file
	    > portdemo					        .... run it!
	    Success: opened parallel port for writing
	    Writing 0 ... Done.
	    Writing 1 ... Done.
	    Writing 2 ... Done.
	    Writing 3 ... Done.
	    Writing 4 ... Done.
	    Writing 5 ... Done.
	    Writing 6 ... Done.
	    Writing 7 ... Done.
	    Writing 8 ... Done.
	    Writing 9 ... Done.
	    >
 */


int theport;	/* File descriptor returned for printer device */


/* This function opens the parallel port for writing, it is a prerequisite for
 * using the port. Returns 1 if the port was opened successfully, or 0 if the
 * operation failed.
 */

int openDevice (void) {
    theport = open ("/dev/plp", O_WRONLY);  /* Open printer port for writes    */
    return ((theport >= 0) ? 1:0);	    /* Return 1 (success) or 0 (fail) */
}


/* This function closes the parallel port when you have finished using it */

void closeDevice (void) {
    close (theport);
}


/* Asserts a reset signal on the parallel port. ie. the reset line is normally
 * high. When you call this function, the RESET signal will pulse low briefly.
 * This could be useful for resetting external hardware, or it could even be
 * used as some sort of handshake.
 */

int resetDevice (void) {
    return (ioctl (theport, PLPIOCRESET, 0) == 0) ? 1:0; /* 1=success, 0=fail */
}



/* This writes a single byte to the parallel port, returning one for success,
 * or 0 for an error condition.
 */

int writeByte (char xbyte) {
    return (write (theport, &xbyte, 1) == 1) ? 1:0;
}


/* Main program... */

void main (void) {
    int n;
    
    if (openDevice()) {	    /* Open the parallel port */
	printf("Success: opened parallel port for writing\n");

	for (n=0;n<10;n++) {
	    fprintf(stderr, "Writing %d ... ", n);
	    if (writeByte (n))
		fprintf(stderr, "Done.\n");
	    else
		fprintf(stderr, "Failed.\n");
	    
	    sginap(50);	    /* Wait for half a second (well, 50 clock ticks) */
	}
    
	closeDevice();	    /* Close the port afterwards */
    } else
	fprintf(stderr, "ERROR: Failed to open parallel port.\n");
}

