/*
  joy_test.c  

  (c) 1996 Till Harbaum / T.Harbaum@tu-bs.de

  test serial joystick interface for unix (requires termios.h)
  (timing problems with linux text console, xterm preferred)

  see http://www.cs.tu-bs.de/~harbaum for hardware
*/

#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/termios.h>

#define JOY_TIMEOUT (100000)

#ifdef sun
#define JOY_DEV_LIST "/dev/ttya","/dev/ttyb"
#endif

#ifdef linux
#define JOY_DEV_LIST "/dev/cua0","/dev/cua1","/dev/cua2","/dev/cua3"
#endif

#ifdef hpux
#define JOY_DEV_LIST "/dev/rs232.1","/dev/rs232.2"
#endif

#ifndef JOY_DEV_LIST
#error Please define some serial devices for your machine!
#endif

char *device_name[]={JOY_DEV_LIST,""};
int  sio_fd;

int
init_joy(void) {
  struct termios sio_term;
  char in_buf;
  int i,dev;
#ifdef hpux
  struct timeval timeout;
  timeout.tv_sec  = 0;
  timeout.tv_usec = JOY_TIMEOUT;
#endif
  
  for(dev=0;device_name[dev][0]!=0;dev++) {
    fprintf(stderr,"%s ",device_name[dev]);

    if((sio_fd = open(device_name[dev], O_RDWR | O_NONBLOCK))<0)
      perror("error opening");
    else {
      /* joystick uses 1200 baud (possible 19200 is untested) */ 
      if(tcgetattr(sio_fd, &sio_term)!=0)
	perror("error getting termio infop");
      else {
	/* We don't want any special function (NO ECHO!!!) but 8 Bit */
	sio_term.c_iflag=0;
	sio_term.c_oflag=0;
	sio_term.c_cflag=CS8|CREAD|HUPCL;
	sio_term.c_lflag=0;
  
	if(cfsetispeed(&sio_term,B1200)!=0)
	  perror("error setting input bit rate");
	else {
	  if(cfsetospeed(&sio_term,B1200)!=0)
	    perror("error setting output bit rate");
	  else {
	    if(tcsetattr(sio_fd, TCSANOW, &sio_term)!=0)
       	      perror("error setting parameters");
	    else {
	      /* hardware setup is done, now detect the joystick */
	      for(i=0;i<10;i++) {              /* try ten times */
		write(sio_fd,"",1);            /* send one byte 0x00 */
#ifdef hpux
                select (0, 0, 0, 0, &timeout);
#else
                usleep(JOY_TIMEOUT);           /* give sio some time to work */
#endif
		while(read(sio_fd,&in_buf,1)>0) {
		  if( ((in_buf&0xe0)==0xc0)&&  /* upper three bits must be 110  */
		      ((in_buf&0x03)!=0x03)&&  /* up & down the same time is impossible */ 
		      ((in_buf&0x0a)!=0x0a)) { /* left & right the same time is impossible */
		    fputs("used for joystick input\n",stderr);
		    return 1;                  /* this seems to be a joystick */
	      } } }
	      fputs("error detecting joystick\n",stderr);
      } } } }
      close(sio_fd);
  } }
  return 0;
}

void
close_joy(void) {
  tcflush(sio_fd,TCIOFLUSH);

  if(sio_fd>=0)
    close(sio_fd);
}

int
get_joy(void) {
  static int ret=0;
  char in_buf;
  while(read(sio_fd,&in_buf,1)>0)
    ret=in_buf&0x1f;
  write(sio_fd,"",1);
  return ret;
}

main(void) {
  int joy;
  char *msg1[]={"CENTER","  UP  "," DOWN "};
  char *msg2[]={"CENTER"," LEFT "," RIGHT"};
#ifdef hpux
  struct timeval timeout;
  timeout.tv_sec  = 0;
  timeout.tv_usec = 20000;
#endif

  puts("serial joystick interface test program");
  puts("(c) 1996 Till Harbaum");
  puts("quit with up/left/fire");

  if(init_joy()) {
    do {
      joy=get_joy();
      printf("\rVerical: %s Horizontal: %s Button: %s",
	     msg1[joy&3],msg2[(joy>>2)&3],
	     (joy&16)?"PRESSED ":"RELEASED");
      fflush(stdout);
#ifdef hpux
      select (0, 0, 0, 0, &timeout);
#else
      usleep(20000);
#endif
    } while((joy&0x15)!=0x15);
    puts("");
  }

  close_joy();
  return 0;
}








