#include <stdio.h> 
#include <string.h>

#include "timer.h"

////---- ADD_2005_10_31
#define TCNT1_VALUE	10000		// 5ms at 2MHz(1:8)
#define TCNT2_VALUE	30000		// 15ms at 2MHz(1:8)
////---- END_ADD

volatile int sys_tick_5ms, sys_tick_1s;		// Tick count

/* Timer handler table */
struct _TIMER_IRQS
{
	TIMER_IRQ timer_irq[MAX_TIMER_CNT];
}TIMER_IRQS;

#if (__C30_VERSION__ >= 300)
void __attribute__((interrupt, auto_psv)) _T1Interrupt(void)
#else
void _ISR _T1Interrupt(void)
#endif
{
	u_char i;

	sys_tick_5ms++;

	for(i=0; i < MAX_TIMER1_CNT; i++)
	{
		if(TIMER_IRQS.timer_irq[i].user_timer_handler)
			(*TIMER_IRQS.timer_irq[i].user_timer_handler)();
	}
	IFS0bits.T1IF = 0;
}

#if (__C30_VERSION__ >= 300)
void __attribute__((interrupt, auto_psv)) _T2Interrupt(void)
#else
void _ISR _T2Interrupt(void)
#endif
{
	u_char i;
	
	if (++sys_tick_1s > 64) /* 1 sec. */
	{	
		sys_tick_1s = 0;
		for(i=MAX_TIMER1_CNT; i < MAX_TIMER_CNT; i++)
		{
			if(TIMER_IRQS.timer_irq[i].user_timer_handler)
				(*TIMER_IRQS.timer_irq[i].user_timer_handler)();
		}
	}
	IFS0bits.T2IF = 0;
}

void init_timer(void)
{
	u_char i;
	int old_ipl;

	SET_AND_SAVE_CPU_IPL(old_ipl, 7);

	for(i=0;i<MAX_TIMER_CNT; i++)
		TIMER_IRQS.timer_irq[i].user_timer_handler = 0;

	IPC0bits.T1IP = 0x02;	//Setup Timer1 interrupt for desired priority level
	IFS0bits.T1IF = 0; 		//Clear the Timer1 interrupt status flag

	IPC1bits.T2IP = 0x03;	//Setup Timer2 interrupt for desired priority level
	IFS0bits.T2IF = 0; 		//Clear the Timer2 interrupt status flag

	TMR1  = 0;          	/* Reset Timer1 to 0x0000 */
	PR1   = TCNT1_VALUE;	/* assigning Period to Timer period register */
	T1CONbits.TCKPS = 0x1;	// 1:8  16MHz -> 2MHz
	T1CONbits.TON = 1;		// start
	sys_tick_5ms = 0;

	TMR2  = 0;          	/* Reset Timer2 to 0x0000 */
	PR2   = TCNT2_VALUE;	/* assigning Period to Timer period register */
	T2CONbits.TCKPS = 0x1;	// 1:8  16MHz -> 2MHz
	T2CONbits.TON = 1;		// start
	sys_tick_1s = 0;

	RESTORE_CPU_IPL(old_ipl);
}

void set_timer(u_int timer, void (*handler)(void)) 
{
	int old_ipl;

	SET_AND_SAVE_CPU_IPL(old_ipl, 7);

	if(timer < MAX_TIMER1_CNT) {
		IEC0bits.T1IE = 1; //Enable Timer1 interrupts
	}
	else {
		IEC0bits.T2IE = 1; //Enable Timer2 interrupts
	}

	if(handler) TIMER_IRQS.timer_irq[timer].user_timer_handler = handler;

	RESTORE_CPU_IPL(old_ipl);
}

void kill_timer(u_int timer)
{
	u_char i;
	u_char bkill;
	int old_ipl;

	SET_AND_SAVE_CPU_IPL(old_ipl, 7);

	if(timer < MAX_TIMER1_CNT)
	{
		bkill = 1;
		for(i = 0; i < MAX_TIMER1_CNT; i++)
		{
			if(TIMER_IRQS.timer_irq[i].user_timer_handler)
			{
				bkill = 0;
				break;
			}
		}
		if(bkill) 
		{
			sys_tick_5ms = 0;
			IEC0bits.T1IE = 0; //Disable Timer1 interrupts
		}
	}
	else
	{
		bkill = 1;
		for(i = MAX_TIMER1_CNT; i < MAX_TIMER_CNT; i++)
		{
			if(TIMER_IRQS.timer_irq[i].user_timer_handler)
			{
				bkill = 0;
				break;
			}
		}
		if(bkill)
		{
			IEC0bits.T2IE = 0; //Disable Timer2 interrupts
			sys_tick_1s = 0;
		}
	}

	RESTORE_CPU_IPL(old_ipl);
}
