/* Library for CX100 frame grabber for Linux */
/* This requires the CX100 device driver */
/* Written by: Danny Sung */
/* Started:  08/14/1995  20:09 */
/* Finished: 08/15/1995  01:01 */

#include <sys/ioctl.h>
#include <unistd.h>
#include <fcntl.h>
#include "cxlib.h"


void cx_init(int cxfd)
/* It should not normally be necessary to call this function, 
	as cx_open() calls it automatically.  It's here mainly for
	completness.
*/
{
	/* This block isn't necessary.  It was used in testing. */
/*
	i = ioctl(cxfd, FG_GET_BASE_PORT, 0);
	i = ioctl(cxfd, FG_GET_ADDRESS, 0);
	i = ioctl(cxfd, FG_WAITVB, 0);
	i = ioctl(cxfd, FG_GRAB, 0);
	i = ioctl(cxfd, FG_ACQUIRE, 0);
*/
	/* This should reset the board */
	ioctl(cxfd, FG_BOARD_OFF, 0);
	ioctl(cxfd, FG_BOARD_ON, 0);

	/* Some values we'll assume for this library */
	ioctl(cxfd, FG_SET_RAM, 1);
	ioctl(cxfd, FG_CX100, 0);
	ioctl(cxfd, FG_SET_VERTICAL_ACCESS, 0);
	ioctl(cxfd, FG_SET_RESOLUTION, 0);

}

int cx_open(char *str)
/* Opens the cx100 device file and calls cx_init().  If *str is a
	NULL pointer, default is to open "/dev/cx100".
	cx_open() returns a file descriptor, which is used in most of
	the cx_...() functions.  Or the value of open() on error */
{
	int rtn;

	if( (rtn = open( str ? str : DEFAULT_DEVICE_FILE, O_RDWR )) != -1 )
		cx_init(rtn);
	return(rtn);
}

int cx_close(int cxfd)
/* Turns off the frame grabber, and closes the file */
/* Returns value of close() */
{
	ioctl(cxfd, FG_BOARD_OFF, 0);
	return(close(cxfd));
}

/* The cx_nopen() and cx_nclose() function calls are placed here for
	completeness.  They generally should not be needed */
int cx_nopen(char *str)
/* Opens the cx100 device file.  If *str is a NULL pointer, 
	default is to open "/dev/cx100".
	cx_nopen() returns a file descriptor, which is used in most of
	the cx_...() functions.
	Returns value of open() */
{
	return( open( str ? str : DEFAULT_DEVICE_FILE, O_RDWR ) );
}

int cx_nclose(int cxfd)
/* Closes the file without turning off the frame grabber */
{
	return( close(cxfd) );
}

int cx_getframe(int cxfd, char *buff, int nbytes)
/* Does a frame grab and places the captured frame in buff.  Will only
	copy nbytes bytes to this buffer.
	cx_getframe() returns the number of bytes required for the entire
	buffer (even if *buff is a NULL pointer).  Or value of read() on
	error.
*/
{
	lseek(cxfd, 0, 0);
	return( read(cxfd, buff, nbytes) );
}

int cx_getpixel(int cxfd, int x, int y)
/* Returns the value of a single pixel in the frame grabber */
/* Note: If doing a lot of these, you might be better off doing a
	cx_getframe() and doing this manually, as this function makes
	several system calls. */
{
	int rtn=0;	/* Note: we need to set this to clear the high byte */
					/* C assumes char is same number of bytes as int anyway */
	ioctl(cxfd, FG_GRAB, 0);
	lseek(cxfd, x, y);
	read(cxfd, &rtn, 1);
	return(rtn);
}

int cx_getresolution(int cxfd)
/* Returns the current resolution the CX100 is in */
{
	return( ioctl(cxfd, FG_GET_RESOLUTION, 0) );
}

int cx_setresolution(int cxfd, int state)
/* Sets the resolution.  "state" == 1 for high, 0 for low res */
/* Returns the new state */
{
	return( ioctl(cxfd, FG_SET_RESOLUTION, state&1) );
}

int cx_imagewidth(int cxfd)
{
	return( ioctl(cxfd, FG_IMAGEWIDTH, 0) );
}

int cx_imageheight(int cxfd)
{
	return( ioctl(cxfd, FG_IMAGEHEIGHT, 0) );
}

