/*********************************************************************
 *
 *                  Tick Manager for PIC18
 *
 *********************************************************************
 * FileName:        Tick.c
 * Dependencies:    Tick.h
 * Processor:       PIC18F67J50
 * Compiler:       	MPLAB C18 (mcc18.exe) v3.35
 * Linker:          MPLAB MPLINK Object Linker (mplink.exe) v4.35
 * Company:         TechToys Company (www.TechToys.com.hk)
 *
 * John Leung		18/08/10
********************************************************************/

#include "tick.h"

//TICK_TEMP_VALUE_1 is basically the TMR0 preload value to obtain
//a (1/(TICKS_PER_SECOND) delay
//For some unknown reason, the statement 
//#define TICK_TEMP_VALUE_1 		((CLOCK_FREQ/4) / (TICKS_PER_SECOND*TICK_PRESCALE_VALUE)) 
//gave us a false value on TICK_TEMP_VALUE_1 in simulation
#define TICK_TEMP_VALUE_1 		((CLOCK_FREQ/4) / TICKS_PER_SECOND / TICK_PRESCALE_VALUE)

#if TICK_TEMP_VALUE_1 > 0xFFFF
#error TICK_PER_SECOND value cannot be programmed with current CLOCK_FREQ
#error Either lower TICK_PER_SECOND or manually configure the Timer
#endif

#define TICK_TEMP_VALUE         (65535 - TICK_TEMP_VALUE_1)

#define TICK_COUNTER_HIGH       ((TICK_TEMP_VALUE >> 8) & 0xff)
#define TICK_COUNTER_LOW        (TICK_TEMP_VALUE & 0xff)


static TICK TickCount = 0;


/*********************************************************************
 * Function:        void TickInit(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          Tick manager is initialized.
 *
 * Side Effects:    None
 *
 * Overview:        Initializes Timer0 as a tick counter in 16-bit mode
 *
 * Note:            None
 ********************************************************************/
void TickInit(void)
{	
	#if (TICK_PRESCALE_VALUE	== 2)	//1:2 prescale value
    	#define TIMER_PRESCALE  0		//T0PS2:T0PS0 = 000
	#elif ( TICK_PRESCALE_VALUE == 4)	//1:4 prescale value
    	#define TIMER_PRESCALE  1		//T0PS2:T0PS0 = 001
	#elif ( TICK_PRESCALE_VALUE == 8)	//1:8 prescale value
    	#define TIMER_PRESCALE  2		//T0PS2:T0PS0 = 010
	#elif ( TICK_PRESCALE_VALUE == 16)	//1:16 prescale value
    	#define TIMER_PRESCALE  3		//T0PS2:T0PS0 = 011
	#elif ( TICK_PRESCALE_VALUE == 32)	//1:32 prescale value
    	#define TIMER_PRESCALE  4		//T0PS2:T0PS0 = 100
	#elif ( TICK_PRESCALE_VALUE == 64)	//1:64 prescale value
    	#define TIMER_PRESCALE  5		//T0PS2:T0PS0 = 101
	#elif ( TICK_PRESCALE_VALUE == 128)	//1:64 prescale value
    	#define TIMER_PRESCALE  6		//T0PS2:T0PS0 = 110		
	#elif ( TICK_PRESCALE_VALUE == 256)	//1:256 prescale value
    	#define TIMER_PRESCALE  7		//T0PS2:T0PS0 = 111
    	#error Invalid TICK_PRESCALE_VALUE specified.
	#endif

    // 16-BIT, internal timer, T0PS2:T0PS0 value set
	// It is a bit tricky to use TMR0 as a 16bit counter here 
	// The default TMR0's width in 8-bit mode. We need to set TMR0 to 16-bit prior
	// to have loaded TMR0H value; else, 'TMR0H = TICK_COUNTER_HIGH' will not be executed
    T0CON = 0x00 | TIMER_PRESCALE;

    TMR0H = TICK_COUNTER_HIGH;
    TMR0L = TICK_COUNTER_LOW;

    // Start the timer.
    INTCONbits.TMR0IF = 0;	//clear the interrupt flag
    INTCONbits.TMR0IE = 1;	//enable interrupt
    T0CONbits.TMR0ON  = 1;	//start TMR0
}


/*********************************************************************
 * Function:        TICK TickGet(void)
 *
 * PreCondition:    None
 *
 * Input:           None
 *
 * Output:          Current second value is given
 *
 * Side Effects:    None
 *
 * Overview:        None
 *
 * Note:            None
 ********************************************************************/
TICK TickGet(void)
{
    return TickCount;
}


/*********************************************************************
 * Function:        void TickUpdate(void)
 *
 * PreCondition:    For isr() routine, inside if(TMR1IF) {...TMR1IF = 0;}
 *
 * Input:           None
 *
 * Output:          None
 *
 * Side Effects:    None
 *
 * Overview:        Internal Tick and Seconds count are updated.
 *
 * Note:            None
 ********************************************************************/
void TickUpdate(void)
{
        TMR0H = TICK_COUNTER_HIGH;
        TMR0L = TICK_COUNTER_LOW;

        TickCount++;
}






