/* VV6300 CMOS camera initialisation routines
 * fileName: vcamInit.c
 * note: documentation in vcamInit.h
 */

#include "vcamInit.h"
#include <unistd.h>
#include <stdio.h>
#include "pc_io.h"
#include "xfcam.h"
#include "vcamFrame.h"

/*********************************************************/

int init ( void )
	{
	/* get Permissions for parallel port */
	/* ioperm is LINUX SPECIFIC -> not portable */
	fprintf ( stderr, "Initialising VV6300...\n" );
	ioperm ( PC_PARALLEL_PORT, 3, 1 );
	
#if QCK_SLOW
	writeMessage ( SETUP_4, 0x44, NO_WAIT_FOR_ACK ); /* set QCK(slow) in free running mode and enable FST */
#else
	writeMessage ( SETUP_4, 0x45, NO_WAIT_FOR_ACK ); /* set QCK in free running mode and enable FST */
#endif
	/*writeMessage ( CLK_DIV, 0x03, NO_WAIT_FOR_ACK );*/ /* set clock divisor to 8 */
	/*writeMessage ( CLK_DIV, 0x03, NO_WAIT_FOR_ACK ); /* set clock divisor to 8 */
	writeMessage ( CLK_DIV, 0x03, NO_WAIT_FOR_ACK ); /* set clock divisor to 8 */
	writeMessage ( SETUP_0, 0x07, NO_WAIT_FOR_ACK ); /* 8-wire parallel mode */
	writeMessage ( SETUP_1, 0x70, NO_WAIT_FOR_ACK ); 

	/* Put parallel port in read mode by setting bit 5 in the control register */
	outb ( 0x20, PAR_CTRL );

	if (testForQCK () == QCK_FOUND)
		{
		fprintf ( stderr, "Found the VV6300\n" );
		return (VV6300);
		}
	else
		{
		fprintf ( stderr, "VV6300 not connected\n" );
		return (NO_CAMERA);
		}
	}

/*********************************************************/

void writeMessage ( BYTE index, BYTE data, BYTE waitAcknowledge )
	{
	BYTE address = WRITE;
	
	/* generate start condition */
	startCondition ();

	/* send message */
	sendByte ( address, NO_WAIT_FOR_ACK );
	sendByte ( index, NO_WAIT_FOR_ACK );
	sendByte ( data, NO_WAIT_FOR_ACK );

	/* generate stop condition */
	stopCondition ();
	}

/*********************************************************/

void stopCondition ( void )
	{
	SCL_set ();
	SDA_set ();
	wait ();
	}

/*********************************************************/

void startCondition ( void )
	{
	SDA_set ();
	SCL_set ();
	wait ();
	SDA_clear ();
	wait ();
	SCL_clear ();
	}

/*********************************************************/

void SDA_set ( void )
	{
	BYTE b;
	
	b = OSReadParCTRL ();
	#if DEBUG
	fprintf ( stderr, "SDA_set CTRL<" );
	printByte ( b );
	fprintf ( stderr, "> " );
	#endif

	b |= SDA;
	OSWriteParCTRL ( b );
	
	#if DEBUG
	fprintf ( stderr, "CTRL<" );
	printByte ( b );
	fprintf( stderr, ">\n" );
	#endif
	
	}
	
/*********************************************************/

void SDA_clear ( void )
	{
	BYTE b;
	
	b = OSReadParCTRL ();
	#if DEBUG
	fprintf ( stderr, "SDA_clear CTRL<" );
	printByte ( b );
	fprintf ( stderr, "> " );
	#endif

	b &= ~SDA;
	OSWriteParCTRL ( b );
	
	#if DEBUG
	fprintf ( stderr, "CTRL<" );
	printByte ( b );
	fprintf( stderr, ">\n" );
	#endif
	}

/*********************************************************/

void SCL_clear ( void )
	{
	BYTE b;
	
	b = OSReadParCTRL ();
	#if DEBUG
	fprintf (stderr, "SCL_clear CTRL<" );
	printByte ( b );
	fprintf (stderr, "> " );
	#endif

	b &= ~SCL;
	OSWriteParCTRL ( b );

	#if DEBUG
	fprintf (stderr, "CTRL<" );
	printByte ( b );
	fprintf (stderr, ">\n" );
	#endif
	}

/*********************************************************/

void SCL_set ( void )
	{
	BYTE b;
	
	b = OSReadParCTRL ();
	#if DEBUG
	fprintf (stderr, "SCL_set CTRL<" );
	printByte ( b );
	fprintf (stderr, "> " );
	#endif

	b |= SCL;
	OSWriteParCTRL ( b );
	
	#if DEBUG
	fprintf (stderr, "CTRL<" );
	printByte ( b );
	fprintf (stderr, ">\n" );
	#endif
	}

/*********************************************************/

void printByte ( BYTE b )
	{
	int i;

	for (i=0; i<8; i++)
		{
		fprintf ( stderr, "%d",((b & 0x80) != 0) );
		b <<= 1;
		}
	}

/*********************************************************/

void sendByte ( BYTE value, BYTE waitAcknowledge )
	{
	int i;

	#if DEBUG_INIT
	fprintf ( stderr, "sendByte <" );
	#endif
	for (i=0; i<8; i++ )
		{
		if ((value & 0x80) == 0)
			{
			SDA_clear ();
			#if DEBUG_INIT
			fprintf ( stderr, "0" );
			putchar ( '0' );
			#endif
			}
		else
			{
			SDA_set ();
			#if DEBUG_INIT
			fprintf ( stderr, "1" );
			putchar ( '1' );
			#endif
			}

		wait (); /* set up data */
		SCL_set (); /* clock */
		wait (); /* let cam read it */
		SCL_clear ();
		wait (); 

		value <<= 1;
		}
	#if DEBUG_INIT
	fprintf ( stderr, ">\n" );
	#endif

	SCL_set ();

	/*for (i=0; i<ACK_WAITS; i++)*/
		wait();
		wait();
	/*
	if (waitAcknowledge == WAIT_FOR_ACK)
		{
		for (i=0; i<ACK_WAITS; i++)
			{
			if (SDA_read () == 0)
				break;

			wait ();
			}
		}
	else
		fprintf ( stderr, "Not waiting for acknowledge\n" );


	if (i >= ACK_WAITS)
		fprintf ( stderr, "Camera didn't acknowledge\n" );
	else
		fprintf ( stderr, "Camera ACKNOWLEDGED!\n" );
	*/
	
	wait ();
	SCL_clear ();
	}

/*********************************************************/

void wait ( void )
	{
	/* sleep ~70 microseconds */
	/*usleep ( 70 );*/
	usleep ( 140 );
	}

/*********************************************************/

int SDA_read (void)
	{
	BYTE b;

	b = OSReadParCTRL () & SDA;
	return (b>0);
	}

/*********************************************************/

