#ifndef PRECOMPHDRS
#include	<tt8lib.h>		/* definitions and prototypes for Model 8 library */
#include	<tpu332.h>

#include	<stdio.h>
#include	<stdlib.h>
#include	<userio.h>
#endif

#include	"tputime.h"

#define			SECONDS_PER_EPOCH		0xFFFF

// DEFINES FOR TPU FUNCTIONS
#define			TPU_ITC_1_HZ			0 // TPU channel for input capture
#define			TPU_ITC_40_KHZ			7

enum 
{
	CHAN_CTRL, 
	LINK_CTRL, 
	MAX_COUNT, 
	TRANS_COUNT, 
	FINAL_TRANS_TIME, 
	LAST_TRANS_TIME
} ITC_Parameters;

enum
{
	LINK_CHAN_CNTRL,
	MAX_COUNT_PERIOD,
	LAST_ACCUM,
	ACCUM,
	ACCUM_RATE_PPWA_UB,
	PPWA_LWs
} PPWA_Parameters;

/* Host Service Request */
#define			ITC_INITIALIZE				1
#define			PPWA_INITIALIZE				2

/* ITC -- Host Sequence */
#define			SINGLE_NO_LINKS				0
#define			CONTINUOUS_NO_LINKS			1
#define         SINGLE_LINKS				2
#define			CONTINUOUS_LINKS			3

/* PPWA -- Host Sequence */
#define			ACCUMULATE_24_BIT_PERIODS	0 // ** WARNING, BROKEN FOR SOME MASKS
#define			ACCUMULATE_16_BIT_PERIODS	1
#define         ACCUMULATE_24_BIT_WIDTHS	2 // ** WARNING, BROKEN FOR SOME MASKS
#define		   	ACCUMULATE_16_BIT_WIDTHS	3

/* PSC -- Pin State Control */
#define			FORCE_BY_PAC				0x00
#define			FORCE_HIGH					0x01
#define			FORCE_LOW					0x02
#define			NO_FORCE					0x03

/* PAC -- Pin Action Control (inputs) */
#define         NO_DETECT		   			0x00
#define         DETECT_RISING           	0x04
#define         DETECT_FALLING          	0x08
#define         DETECT_EITHER           	0x0C
#define         PAC_NO_CHANGE				0x10

/* PAC -- Pin Action Control (outputs) */
#define			NO_CHANGE_ON_MATCH			0x00
#define			HIGH_ON_MATCH				0x04
#define			LOW_ON_MATCH            	0x08
#define			TOGGLE_ON_MATCH				0x0C

/* TBS -- Time Base/Directionality Control */
#define         INPUT_CHAN              	0x00
#define			OUTPUT_CHAN					0x80
#define         CAPTURE1_MATCH1				0x00
#define         CAPTURE1_MATCH2				0x20
#define			CAPTURE2_MATCH1         	0x40
#define			CAPTURE2_MATCH2         	0x60
#define        	TBS_NO_CHANGE				0x100

static  ulong		tpuSeconds;
static	ExcCFrame	framebuf;

void	SetupOneSecondInterrupt(ushort chan);
void	SetupTransitionCounter(ushort chan);
void    OneSecondInterrupt(void);
void	ResetTPUCount(ushort chan);

long	GetTPUCount(ushort chan);

void TPU_InitializeTimeKeeping()
{
	SetupOneSecondInterrupt(TPU_ITC_1_HZ);
	SetupTransitionCounter(TPU_ITC_40_KHZ);
	tpuSeconds = 0;
}

void TPU_SetTimeTM(struct tm *tp, vfptr sync)
{
	time_t value;
	value = mktime(tp);
	if (sync != (vfptr) NULL) 
		(*sync)();
	tpuSeconds = value;
}

time_tt TPU_ttmnow()
{
	time_tt now;
	ushort  mask;

	mask = GetInterruptMask();     
	SetInterruptMask(NO_RUPTS_MASK);
	now.secs  = tpuSeconds;
	now.ticks = GetTPUCount(TPU_ITC_40_KHZ);
	SetInterruptMask(mask);
	
	//  Ticks should never be greater than 39999.  Larger numbers
	//  may confuse other parts of the software, so prevent them.
	if (now.ticks >= 40000)
		now.ticks = 39999;
	return now;
}

void SetupOneSecondInterrupt(ushort chan)
{
	TPUInterruptDisable(chan);

	// SETUP CHANNEL
	InstallHandler(OneSecondInterrupt, TPU_INT_VECTOR + chan, &framebuf);
	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]	= DETECT_RISING;	 // count rising edges
	PRAM[chan][LINK_CTRL]	= 0x0E;				 // no links
	PRAM[chan][MAX_COUNT]	= 1; // maximum count

	HOSTSEQ(chan, CONTINUOUS_NO_LINKS); // continuous count, no links
	HOSTSERVREQ(chan, ITC_INITIALIZE);	// init
	CHANPRIOR(chan,HighPrior);			// priority
	while(HOSTSERVSTAT(chan) & 3) 		// poll until service ends (00)
		;
	TPUClearInterrupt(chan);
	TPUInterruptEnable(chan);
}

void SetupTransitionCounter(ushort chan)
{
	TPUInterruptDisable(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]	= DETECT_RISING;	 // count rising edges
	PRAM[chan][LINK_CTRL]	= 0x0E;				 // no links
	PRAM[chan][MAX_COUNT]	= 41000;			 // maximum count

	HOSTSEQ(chan, CONTINUOUS_NO_LINKS); // continuous count, no links
	HOSTSERVREQ(chan, ITC_INITIALIZE);	// init
	CHANPRIOR(chan,MiddlePrior);
	while(HOSTSERVSTAT(chan) & 3) 		// poll until service ends (00)
		;
}

long GetTPUCount(ushort chan)
{	
	return ((ulong) (PRAM[chan][TRANS_COUNT]));	// get count
}

void ResetTPUCount(ushort chan)
{	
   PRAM[chan][TRANS_COUNT] = 0;
}

void OneSecondInterrupt(void)
{	
	ResetTPUCount(TPU_ITC_40_KHZ); 
	tpuSeconds++;
	TPUClearInterrupt(TPU_ITC_1_HZ);
}








