/****************************************************************************/
/*                                                                          */
/*  VolVis is a volume visualization system for investigating, manipulating */
/*  and rendering geometric and volumetric data.                            */
/*                                                                          */
/*  Copyright (C) 1993 by the Research Foundation of the State University   */
/*                            of New York                                   */
/*                                                                          */
/*  This program is free software; you can redistribute it and/or modify    */
/*  it under the terms of the GNU General Public License as published by    */
/*  the Free Software Foundation; either version 1, or (at your option)     */
/*  any later version.                                                      */
/*                                                                          */
/*  This program is distributed in the hope that it will be useful,         */
/*  but WITHOUT ANY WARRANTY; without even the implied warranty of          */
/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the           */
/*  GNU General Public License for more details.                            */
/*                                                                          */
/*  You should have received a copy of the GNU General Public License       */
/*  along with this program; if not, write to the Free Software             */
/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.               */
/*                                                                          */
/*  For information on VolVis, contact us at:                               */
/*                                                                          */
/*                volvis@cs.sunysb.edu                         (email)      */
/*                                                                          */
/*                Lisa Sobierajski & Ricardo Avila             (US Mail)    */
/*                Department of Computer Science                            */
/*                State University of New York at Stony Brook               */
/*                Stony Brook, New York  11794-4400                         */
/*                                                                          */
/****************************************************************************/





/*********************************************************************
* * * Copyright (c) 1988 by Arie Kaufman and his employer the * *
Research Foundation of the State University of New York * * *
*********************************************************************/

#include <sys/time.h> 
#include <sys/file.h> 
#include <sgtty.h>
#ifndef C_SGI
#include <errno.h>
#endif

#include "cube.h"
#include "iso_module.h"
#include "iso.h"

#define misc_stub(x) printf(x);

static	char	*index(), *cp, *portb = "/dev/tty00", buf[BUFSIZ],
cr = CR,	/* the carriage return			*/
sys_rs = RS;	/* isotrak reset control character	*/

static	unsigned	int	s =1; static	struct	timeval
time_out; static	int	errno, cc, readfrom, check_err(),
opn_flag = FALSE, /* the /dev/ptyb is opened to isotrak */
wait_time =100000,
/* the time waited for the respond after the command string is sent to isotrak	*/
fd,		/* file-pointer to isotrak		*/
isoerrno,	/* error code during isotrak operations*/
sys_item_cnt,	/* the number of data items be returned from isotrak	*/
sys_item_tbl[32]; /* what data items are returned from the isotrak	*/
static	void	wait();


/*									*/
/*	Initialization of isotrak, this routine must be called		*/ 
/*	before any command function is invoked.				*/
/*									*/

int initial_isotrak() 
{ 
	struct sgttyb basic; 	float x;
        int	 connected;
        printf("hello,world\n");
	isoerrno = 0; 
	if ((fd=open(portb, O_RDWR, 0)) < 0) {
            isoerrno = EISOOPEN;
     	    return(-1); 
	} 
	ioctl(fd,TIOCGETP, &basic);
 	basic.sg_ispeed = basic.sg_ospeed = B9600;
        basic.sg_flags = RAW | TAB0 ;
 	ioctl(fd, TIOCSETP, &basic);
        opn_flag = TRUE;
 	time_out.tv_sec = time_out.tv_usec = 0;

/* try to get something back from isotrak to see it turn on or not */ 

	connected = inquire_increment(&x); 
        printf("connected: %d\n", connected );
 	if (connected == -1)
 		connected =inquire_increment(&x);
 	if (connected == -1) {
 		isoerrno =EISOOPEN; 
        printf("connected2: %d\n", connected );
        close(fd); 	} 
	return(ERR_IMG(isoerrno)); 
}

int close_isotrak() 
{ 
	close(fd); 
	opn_flag = FALSE;
}

/*									*/
/*	The following functions are used for Alignment of isotrak	*/
/*									*/

int set_alignment(Ox, Oy, Oz, Xx, Xy, Xz, Yx, Yy, Yz) 
float	Ox, Oy, Oz, Xx, Xy, Xz, Yx, Yy, Yz; 
{ 
	int send_str();

	isoerrno = 0; 
	sprintf(buf, "A1,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f,%.2f%c",
 	                Ox, Oy, Oz, Xx, Xy, Xz, Yx, Yy, Yz, cr);
 	send_str(buf);
        return(ERR_IMG(isoerrno));
}

int reset_alignment() 
{ 
	int send_str();

	isoerrno = 0; 
	sprintf(buf, "R1%c", cr);
 	send_str(buf);
 	return(ERR_IMG(isoerrno));
}

int inquire_alignment(Ox, Oy, Oz, Xx, Xy, Xz, Yx, Yy, Yz) 
float	*Ox, *Oy, *Oz, *Xx, *Xy, *Xz, *Yx, *Yy, *Yz; 
{ 	
	int send_str();

        isoerrno = 0;
        sprintf(buf, "A1%c", cr); 
	cc = send_str(buf); 
	if (cc > 0) 
         {
          if ( ISREC(buf) && ISALIGN(buf))
          sscanf(&buf[3], 
           "%7f%7f%7f%7f%7f%7f%7f%7f%7f", Ox, Oy, Oz, Xx, Xy, Xz, Yx, Yy, Yz);  
        	} 	
        else
           isoerrno = EISOGDATA;
       	return(ERR_IMG(isoerrno)); 
}

/*									*/
/*	The following functions are used for Boresight of isotrak	*/
/*									*/

int set_boresight() 
{ 
	int send_str();

	isoerrno = 0;
 	sprintf(buf, "B1%c", cr);
        send_str(buf);
 	return(ERR_IMG(isoerrno));
 }

int reset_boresight() 
{ 
	int send_str();

	isoerrno = 0;
 	sprintf(buf, "b1%c", cr);
 	send_str(buf); 
	return(ERR_IMG(isoerrno));
 }



/*									*/
/*	The functions for Envelope					*/
/*									*/

int set_envelope(Xmax, Ymax, Zmax, Xmin, Ymin, Zmin)
float	Xmax, Ymax, Zmax, Xmin, Ymin, Zmin;
{
	int send_str();

 	isoerrno = 0;
 	sprintf(buf,"V1,%f,%f,%f,%f,%f,%f%c",
                 Xmax, Ymax, Zmax, Xmin, Ymin, Zmin, cr);
 	send_str(buf);
 	return(ERR_IMG(isoerrno));
 }

int inquire_envelope(Xmax, Ymax, Zmax, Xmin, Ymin, Zmin)
float *Xmax, *Ymax, *Zmax, *Xmin, *Ymin, *Zmin;
{
	int send_str();

 	isoerrno = 0; 
	sprintf(buf, "V1%c", cr);
 	cc = send_str(buf); 
	if (cc > 0) 
         { 		
          if ( ISREC(buf) && ISENVEL(buf))
     sscanf(&buf[3], "%7f%7f%7f%7f%7f%7f", Xmax, Ymax, Zmax, Xmin, Ymin, Zmin); 	} 	
        else
 		isoerrno = EISOGDATA;
        return(ERR_IMG(isoerrno));
 }




/*									*/
/*	The functions for Hemisphere					*/
/*									*/

int set_hemisphere(LOSx, LOSy, LOSz)
 float	LOSx, LOSy, LOSz; 
{
	int send_str();

        isoerrno = 0;
 	sprintf(buf, "H1,%f,%f,%f%c", LOSx, LOSy, LOSz, cr);
        send_str(buf);
 	return(ERR_IMG(isoerrno));
 }

int set_hemisphere_by_isotrak() 
{ 
	int send_str();

	isoerrno = 0;
 	sprintf(buf, "H1%c", cr);
 	send_str(buf);
 	return(ERR_IMG(isoerrno)); 
 }

int inquire_hemisphere(LOSx, LOSy, LOSz)
 float *LOSx, *LOSy, *LOSz;
 {
	int send_str();

        isoerrno = 0;
       	sprintf(buf, "H%c", cr);
 	cc = send_str(buf);
        if (cc > 0) 
         { 		
           if ( ISREC(buf) && ISHEMI(buf))
           sscanf(&buf[3], "%7f%7f%7f", LOSx, LOSy, LOSz);
 	} 	
        else
         isoerrno = EISOGDATA;
 	return(ERR_IMG(isoerrno));
 }



/*									*/
/*	The functions for Increment					*/
/*									*/

int set_increment(increment)	
/* default is 0.0			*/ 
float	increment;  
{ 	
	int send_str();

        isoerrno = 0;
        sprintf(buf, "I%f%c", increment, cr);
       	send_str(buf);
        return(ERR_IMG(isoerrno));
}

int inquire_increment(increment) 
float	*increment; 
{ 
	int send_str();

	isoerrno = 0;
        sprintf(buf, "I%c", cr); 
 	cc = send_str(buf);
 	if (cc > 0) {
          if (ISREC(buf) && ISINCRE(buf))
           sscanf(&buf[3], "%7f", increment);
               	}
 	else
          isoerrno = EISOGDATA;
 	return(ERR_IMG(isoerrno)); 
}



/*									*/
/*	The functions to control the data-items which			*/ 
/*	will be return when the inquire_data() is called.		*/
/*									*/

int set_output_list(item_tbl, item_cnt) 
int     item_tbl[];

/*                      cannot more than 32 items			*/

int	item_cnt;

/*
tell the number of data items is available
when data is read from isotrak.

Available item codes are:
1) Cartesian Coordinates :2,
2) Orientation(Azimuth,Elevation,Roll):4
3) Sensor X-axis Direction Cosines:5
   Sensor Y-axis Direction Cosines:6
   Sensor Z-axis Direction Cosines:7
4) Orientation Quaternion:11			
*/

{
 	misc_stub("set_output_list");
 }



int reset_output_list()	
/* default data-items is 2 and 4		*/ 
{ 	
	int send_str();

          isoerrno = 0; 	
          sprintf(buf, "k");
          send_str(buf);
       	return(ERR_IMG(isoerrno));
 }



/*									*/
/*	The followings are misllances functions                         */
/*									*/

int reset_isotrak()	 	
/* reset the isotrak to default values again				*/ 
{ 
	int send_str();

	isoerrno = 0;
        sprintf(buf, "%c", sys_rs); 
	send_str(buf);
 	sys_item_cnt = 2;
        sys_item_tbl[0] = 2;
 	sys_item_tbl[1] = 4;
        return(ERR_IMG(isoerrno));
}

int inquire_data(data) 
struct	_isodata *data;  
{
	int send_str();

        misc_stub("inquire_data");
/* 
       int	 cnt, cp=2;
       isoerrno = 0;
       sprintf(buf, "P");
       cc = send_str(buf); 
       if (cc > 0) 
       {
        if (ISDATA(buf)) 
        { 	 
         for (cnt=0; cnt<sys_item_cnt; cnt++) 
          {
            switch(sys_item_tbl[cnt]) 
             { 	 case 2: 
                  {
                    sscanf(&buf[cp], "%7.2f %7.2f %7.2f", 			                       posx(data), posy(data), posz(data)); 			                    cp += 24;
                  }
         	 case 4:
                  {
               	sscanf(&buf[cp], "%7.2f %7.2f %7.2f",
 			 azi(data), eva(data), roll(data));
                   cp += 24;
  		 } 	 
                 case 5: 
                   {
                sscanf(&buf[cp], "%7.2f %7.2f %7.2f", 
 			 xcosx(data), xcosy(data), xcosz(data)); 			           cp += 24;
                   } 
 	        case 6: 
                  {
		sscanf(&buf[cp], "%7.2f %7.2f %7.2f",
 			 ycosx(data), ycosy(data), ycosz(data)); 		               	cp += 24;
 		 } 	 
                case 7:
                 {
		sscanf(&buf[cp], "%7.2f %7.2f %7.2f",
                 zcosx(data), zcosy(data), zcosz(data)); 			                cp += 24;
  		 } 	 
                case 11:
                 {
                sscanf(&buf[cp], "%7.2f %7.2f %7.2f %7.2f",
                q1(data), q2(data), q3(data), q4(data));
                cp += 32;
 		 } 	
                 defaule: break;
             	} } } }
            return(ERR_IMG(isoerrno)); */
 }


int inquire_status(status) 
struct	_isostatus *status; 
{
  misc_stub("inquire_status");
}

int set_units(unit)
char	unit;		/* INCH or CENTIMETER default is INCH   */
{
	int send_str();

	isoerrno = 0;
	if (unit == INCH || unit == CENTIMETER) {
		sprintf(buf, "%c", unit);
		send_str(buf);
	} else isoerrno = EISOUNIT;
	return(ERR_IMG(isoerrno));
}


int get_position(x, y, z)
float	*x, *y, *z;
{
	int send_str();

	char    obuf[BUFSIZ];

	isoerrno = 0; 
	sprintf(obuf, "O2,1%c", cr);
 	if (send_str(obuf) < 0)
		return(ERR_IMG(isoerrno));
	sprintf(obuf, "P");
	cc = send_str(obuf);
	if ((cc > 0) && (ISDATA(obuf))) 
            {
		sscanf(&obuf[3], "%7f%7f%7f", x, y, z);
	}
	else 
		isoerrno = EISOGDATA;
	return(ERR_IMG(isoerrno));
}

int get_orientation(x, y, z)
float	*x, *y, *z;
{
	int send_str();

	char    obuf[BUFSIZ];

	isoerrno = 0;
	sprintf(obuf, "O4,1%c", cr);
	if (send_str(obuf) < 0)
		return(ERR_IMG(isoerrno));
	sprintf(obuf, "P");
	cc = send_str(obuf);
	if ((cc > 0) && (ISDATA(obuf)))
		sscanf(&obuf[3], "%7f%7f%7f", x, y, z);
	else 
		isoerrno = EISOGDATA;
	return(ERR_IMG(isoerrno));
}

int setup_fmt()
{
	int send_str();

	char    obuf[BUFSIZ];

	sprintf(obuf, "O2,1%c", cr);
	if (send_str(obuf) > 0)
		return(-1);
	else return(0);
}



/*									*/
/*	L O C A L	    R O U T I N E S				*/
/*									*/

int send_str(str)
/*
*	purpose:	send a string to the isotrak, and then
*			receive a string from the isotrak if 
*			there is any.
*
*	input:		str	the pointer to a buffer which is
*				holding the string to be send to 
*				isotrak
*
*	output:		return the number of characters receive
*			from the isotrak.
*/
char	str[];
{
	int	ready, bufsiz, num=0;
	char	*pt, tmp[BUFSIZ];

	if ((bufsiz = strlen(str)) > 0)
		(void) write(fd, str, strlen(str));

	wait(1, wait_time);

	readfrom = (1<<fd);
	pt = str;
	do {
		ready = readfrom;
		(void) select(32, &ready, (int *)0, (int *)0, &time_out);
		if (ready & (1<<fd)) {
			errno =0;
			cc = read(fd, tmp, BUFSIZ);
			if (cc <= 0) {
				if (errno != EWOULDBLOCK)
					readfrom &= ~(1<<fd);
			} else {
				sprintf(pt, "%s", tmp);
				pt += cc;
				num += cc;
				if (str[num - 1] == '\n') break;
			}
		}
		else break;
	} while (readfrom);
	str[num] = '\0';
	isoerrno = check_err(str);
	return(num);
}

/*****************************************************************************/
/*									     */
/* function:	wait (n, m) 						     */
/*									     */
/* purpose:	Provide a wait state for data arrival.			     */
/*									     */
/* inputs:	n	primary loop control variable.			     */
/*		m	secondary loop control variable.		     */
/*									     */
/* output:	none.							     */
/*									     */
/*****************************************************************************/
static 	void
wait (n, m)
int 	n,m;
{
	int i, j, k;

	k = 1;
	for (i = 0; i < n; i++)
		for (j = 0; j < m; j++)
			k *= 1;
}

static	int
check_err(str)
char	str[];
{
	if (strlen(str) > 3) {
		if (ISREC(str) && ISERR(str))
			return(atoi(ERR_CODE(str)));
		if (ISBITERR(str))
			return((int) (str[0]));
	}
	return(0);
}
