#include	"Camtt10.h"

/******************** Definitions ***************************/

#define		MOTOR_PERIOD		5	// Half the period in ms
#define		CW					1
#define		CCW					0
#define		PWR_CAL				710
#define		STRB1_CAL			38L
#define		STRB2_CAL			38L
#define		STRB3_CAL			38L
#define		STRB4_CAL			38L

#define		LENS_STEPS			1800

#define		COM2_TX			13
#define		COM2_RX			14
#define		TSBUFSIZ		1024
#define		COM1_BAUD		57600L
#define		COM2_BAUD		57600L

/********************* Function Prototypes *******************/

void 	motor_step(int steps, int dir);
void	SetupTPUCount(short chan);
long	GetTPUCount(short chan);
int		lens_wipe_cycle(void);
void	delay_w_break(long secs);
void 	TPUiorelay(void);
void TPUiorelay_timed(time_t delay);


/*********************** Macros *********************/

#define		motor_enable()		PSet(D,3);			// Turn motor driver on
#define		motor_disable()		PClear(D,3);		// Turn motor driver off


/*********************** Global Variables *********************/

/*********************************************************************************
	main
*******************************************************************************/

void main(void)
{
	char charbuf[10];

/***************** Init pins ***************************/

	InitTT8(NO_WATCHDOG, TT8_TPU);   /* setup Model 8 for running C programs */
	TPUGetPin(0);					// Photo Mult. 1
	TPUGetPin(1);					// Photo Mult. 2
	TPUGetPin(2);				// Hall Sig.
  	TPUSetPin(3, 0);			// Mot Phase 1
  	TPUSetPin(4, 0);			// Mot Phase 2
  	TPUSetPin(5, 0);			// Strobe 4
  	TPUSetPin(6, 0);			// Strobe 3
  	TPUSetPin(7, 0);			// Strobe 2
  	TPUSetPin(8, 0);			// Strobe 1

  	PConfOutp(D,3);				// Motor Enable
  	PClear(D,3);
  	PConfOutp(D,4);				// Turn CPU off
  	PSet(D,4);
  	PConfOutp(D,5);				// Turn Camera off
  	PSet(D,5);
  	

/**************** Setup COM ports ************************/

 	SimSetFSys(14720000L);		// Change system clock to compatible rate
 	SerSetBaud(COM1_BAUD, 0);		// Change COM1 baud rate
	SerSetInBuf(malloc(TSBUFSIZ), TSBUFSIZ);
	
	// COM2 TX
	if(TSerOpen(COM2_TX, HighPrior, OUTP, malloc(TSBUFSIZ+TSER_MIN_MEM), TSBUFSIZ, COM2_BAUD, 'N', 8, 1) != tsOK)
	{
		printf("\nFailed TSerOpen output");
		return;
	}

	// COM2 RX
	if(TSerOpen(COM2_RX, HighPrior, INP, malloc(TSBUFSIZ+TSER_MIN_MEM), TSBUFSIZ, COM2_BAUD, 'N', 8, 1) != tsOK)
	{
		printf("\nFailed TSerOpen input");
		return;
	}



// ****************** Main Program Loop ***********************

	PutStr("\nCamtt10\n\n\n");

  	while(1)		// Wait for commands
  	{
  		SerInFlush();
		PutStr("\n\nCamtt: ");
		gets(charbuf);

		if(!strcmp(charbuf, "wipelens"))		lens_wipe_cycle();
		
		else if(!strcmp(charbuf, "motcw"))
		{
			motor_enable();
			motor_step(120, CW);
			motor_disable();
		}

		else if(!strcmp(charbuf, "motccw"))
		{
			motor_enable();
			motor_step(120, CCW);
			motor_disable();
		}

		else if(!strcmp(charbuf, "reset"))			ResetToMon();

		else if(!strcmp(charbuf, "strb1on"))		TPUSetPin(8,1);
		else if(!strcmp(charbuf, "strb2on"))		TPUSetPin(7,1);
		else if(!strcmp(charbuf, "strb3on"))		TPUSetPin(6,1);
		else if(!strcmp(charbuf, "strb4on"))		TPUSetPin(5,1);
		else if(!strcmp(charbuf, "strb1off"))		TPUSetPin(8,0);
		else if(!strcmp(charbuf, "strb2off"))		TPUSetPin(7,0);
		else if(!strcmp(charbuf, "strb3off"))		TPUSetPin(6,0);
		else if(!strcmp(charbuf, "strb4off"))		TPUSetPin(5,0);

		else if(!strcmp(charbuf, "pcbaud96"))
		{
			TSerResetBaud(13, 9600L);
			TSerResetBaud(14, 9600L);
		}

		else if(!strcmp(charbuf, "pcbaud192"))
		{
			TSerResetBaud(13, 19200L);
			TSerResetBaud(14, 19200L);
		}

		else if(!strcmp(charbuf, "pcbaud384"))
		{
			TSerResetBaud(13, 38400L);
			TSerResetBaud(14, 38400L);
		}
		
		else if(!strcmp(charbuf, "pcbaud576"))
		{
			TSerResetBaud(13, 57600L);
			TSerResetBaud(14, 57600L);
		}

		else if(!strcmp(charbuf, "pcbaud1152"))
		{
			TSerResetBaud(13, 115200L);
			TSerResetBaud(14, 115200L);
		}

		else if(!strcmp(charbuf, "pccom"))			TPUiorelay();
		else if(!strcmp(charbuf, "pcon"))			PClear(D,4);
		else if(!strcmp(charbuf, "pcoff"))			PSet(D,4);
		else if(!strcmp(charbuf, "camon"))			PClear(D,5);
		else if(!strcmp(charbuf, "camoff"))			PSet(D,5);

		else if(!strcmp(charbuf, "status"))
		{
			printf("\nPower = %6.2f V\n", (float)AtoDReadWord(0)/PWR_CAL);
			printf("Strobe 1 Volt = %7.2f V\n", (float)AtoDReadWord(1)/STRB1_CAL);
			printf("Strobe 2 Volt = %7.2f V\n", (float)AtoDReadWord(2)/STRB2_CAL);
			printf("Strobe 3 Volt = %7.2f V\n", (float)AtoDReadWord(3)/STRB3_CAL);
			printf("Strobe 4 Volt = %7.2f V\n", (float)AtoDReadWord(4)/STRB4_CAL);
			printf("Hall Sig. = %d\n", TPUGetPin(2));
		}
		
		else	PutStr("\nWhat?");

    }

}	/* main() */


/***************************************************/


int lens_wipe_cycle(void)
{
	time_t time_out;
	
	SerInFlush();

		motor_enable();
		DelayMilliSecs(500);
		
		time_out = time(NULL) + 600;	// 10 min timeout
		PutStr("\nRotating brush to start point");
		
		// Rotate to start point
		while( TPUGetPin(2) )		// Watch Hall Effect sensor
		{
			if(time_out < time(NULL)) return;
			motor_step(10, CCW);
		}

		PutStr("\nBrush at start point");
		DelayMilliSecs(500);
		

		// Rotate across lens
		PutStr("\nRotating aross lens");
		motor_step(LENS_STEPS, CW);
		DelayMilliSecs(500);

		// Rotate back to start point
		PutStr("\nRotating back to start");
		motor_step(LENS_STEPS, CCW);
		motor_disable();

}

/***************************************************/


void delay_w_break(long secs)
{
	long t;
	
	PutStr("\nWaiting...press any key to skip");
	for(t=0; t<secs; t++)
	{
		if(SerByteAvail()) break;
		DelayMilliSecs(1000);
	}
}


/***************************************************/


void motor_step(int steps, int dir)
{
	int step;

	if(dir)		// CW rotation
	{
		TPUSetPin(3, 0);	// Clear PH1
		TPUSetPin(4, 0);	// Clear PH2
		DelayMilliSecs(MOTOR_PERIOD);

		for(step=0; step<steps; step++)
		{
  			DelayMilliSecs(MOTOR_PERIOD);
			TPUSetPin(4, 1);	// Set PH2
	 		DelayMilliSecs(MOTOR_PERIOD);
	  		TPUSetPin(3, 1);	// Set PH1
	  		DelayMilliSecs(MOTOR_PERIOD);
	  		TPUSetPin(4, 0);	// Clear PH2
	  		DelayMilliSecs(MOTOR_PERIOD);
	  		TPUSetPin(3, 0);	// Clear PH1
		}
	}

	else		// CCW rotation
	{
		TPUSetPin(3, 0);	// Clear PH1
 		TPUSetPin(4, 0);	// Clear PH2
		DelayMilliSecs(MOTOR_PERIOD);
		DelayMilliSecs(MOTOR_PERIOD);

		for(step=0; step<steps; step++)
		{
	  		DelayMilliSecs(MOTOR_PERIOD);
			TPUSetPin(3, 1);	// Set PH1
	 		DelayMilliSecs(MOTOR_PERIOD);
	  		TPUSetPin(4, 1);	// Set PH2
	  		DelayMilliSecs(MOTOR_PERIOD);
	  		TPUSetPin(3, 0);	// Clear PH1
	  		DelayMilliSecs(MOTOR_PERIOD);
	  		TPUSetPin(4, 0);	// Clear PH2
		}
	}

}


//**************************************************************************
// Setup channel for count input
//**************************************************************************

void	SetupTPUCount(short chan){

	// SETUP CHANNEL
	TPUGetPin(chan);		//Set pin as input

	CHANPRIOR(chan,Disabled);
	*CISR ^= (1 << chan );		// Clear any pending interrupt
	*CIER &= ~(1 << chan);		// disable interrupt
	FUNSEL(chan,ITC);		// select input capture function

	PRAM[chan][CHAN_CTRL]	= DetRising;	// what to count (edges)
	PRAM[chan][LINK_CTRL]	= 0x0E;		// no links
	PRAM[chan][MAX_COUNT]	= 0xFFFF;	// maximum count

	HOSTSEQ(chan,ContinuousNoLinks); // continuous count, no links

	HOSTSERVREQ(chan,Initialize);	// init

	CHANPRIOR(chan,MiddlePrior);	// priority

	while(HOSTSERVSTAT(chan)&3) 	// poll until service ends (00)
		;

	}


//**************************************************************************
// Get current channel count
//**************************************************************************

long	GetTPUCount(short chan){

	// Poll Interrupt Bit to check for overflow
	if ( ((*CISR & (1 << chan )) != 0) )
	  {					// if overflow
	   *CISR ^= (1 << chan );		// Clear interrupt bit
	   PRAM[chan][TRANS_COUNT] = 0;	// reset count
	  }
	return(PRAM[chan][TRANS_COUNT]);	// get count
	}


/***************************************************
	TPUiorelay
	Connects COM1 to COM2 to allow commands to be issued.
	Function returns after Ctrl-C detected on COM1.
***************************************************/

void TPUiorelay(void)
{
	int inkey;

	printf("\nPress Ctrl-C to exit...\n");

	while(1)
	{
		if( SerByteAvail() )
		{
		  inkey = (int)SerGetByte();
		  if( inkey == 3 ) break;            /* Exit on Ctrl-C */
		  TSerPutByte(COM2_TX, inkey );
		}

		if( TSerByteAvail(COM2_RX) )
		{
		  SerPutByte((unsigned char)TSerGetByte(COM2_RX));
		}
	}

  return;
}

/***************************************************
	TPUiorelay_timed
	Connects COM1 to COM2 to allow file transfer via
	X or ZMODEM. Function returns after "delay" seconds of
	inactivity.
	
	In:	delay -- delay time in seconds
	Out: None
	
***************************************************/

void TPUiorelay_timed(time_t delay)
{
	int		inkey;
	time_t	timeout;
	
	timeout = time(NULL) + delay;
	
	while(1)
	{
		if( SerByteAvail() )
		{
			timeout = time(NULL) + delay;
		  	inkey = (int)SerGetByte();
		  	TSerPutByte(COM2_TX, inkey );
		}

		if( TSerByteAvail(COM2_RX) )
		{
		  	SerPutByte((unsigned char)TSerGetByte(COM2_RX));
		}
		
		if(timeout < time(NULL)) break;
	}

  return;
}