/**
 * An example of use of the 16-bit timer1 oscillator and interrupt.
 *
 * The pic16f628a can drive its timer1 module just by hanging a standard
 * 32-khz watch crystal across pins B7 and B8 and enabling a few 
 * register bits!  (It even seems to work without the fiddly capacitors,
 * though the crystal accuracy's got to be horrendous without them.)
 *
 * The point of this, beyond very precise timing, is the ability of this
 * timer to wake the chip out of sleep -- something its own internal
 * timer cannot do, since it sleeps with everything else.
 *
 * Here we're repeatedly putting the chip to sleep and letting the
 * timer1 overflow interrupt wake it up every second.
 * Since the counter overflows at 65536 counts, and the watch crystal
 * only generates 32768 cycles per second, we have to fudge the timer
 * value if we want precisely one interrupt per second, setting it
 * half-full, i.e. 32768, every interrupt.
 *
 * See 7.0:  Timer1 module in the pic16f628a datasheet for detailed 
 * info.
 */
#define __16f628a
#include "pic16f628a.h"
#include "tsmtypes.h"
//#include "tsmpic.h"
 
// Set the __CONFIG word:
// I usually set it to _EXTCLK_OSC&_WDT_OFF&_LVP_OFF&_DATA_CP_OFF&_PWRTE_ON
Uint16 at 0x2007  __CONFIG = CONFIG_WORD;

#define SLEEP()	do	{	__asm	SLEEP	__endasm;	} while(0)

static void Intr(void) interrupt 0
{
	if(TMR1IF)
	{
		/**
		 * 32768 hz / 65536 cyles per interrupt = 0.5 interrupts 
		 * per second.  If we want to count seconds, that's a 
		 * touch slow.
		 *
		 * We can fudge the numbers, though.  It should be safe
		 * to write to TMR1H right after an interrupt -- TMR1L
		 * won't have had time to overflow yet -- so we set it
		 * to the high-word of 32768.  Now it'll only take
		 * one second to count up to 65536 again, getting us
		 * one interrupt per second.
		 */
		TMR1H=(32768 >> 8);

		PORTA++;	// Increment PORTA to prove the interrupt works
		TMR1IF=0;	// Clear interrupt flag.
	}
//	GIE=1;		// Globally enable interrupts.
			/** We don't need to do this ourselves since
			 *  the compiler ALWAYS ADDS THIS FOR US
			 *  in interrupt functions!
			 *  If you try and DISable interrupts in an
			 *  interrupt function it WON'T WORK since
			 *  the compiler ALWAYS turns them back ON!
			 */
}

void main(void)
{
	TRISA = 0x00;	// All Port A latch outputs are enabled.
//	TRISB = 0x00 | 0x80 | 0x40; // B7 and B6 should be inputs.

#ifdef  __16f628a	// Only compile this section for PIC16f628a
	CMCON = 0x07;	/** Disable comparators.  NEEDED FOR NORMAL PORTA
			 *  BEHAVIOR ON PIC16f628a!
			 */
#endif

	T1CKPS0=0;	// Set Timer1 prescaler to 1:1
	T1CKPS1=0;

	T1OSCEN=1;	// Enable crystal oscillator across B6/B7
	NOT_T1SYNC=1;	// Do not synchronize external clock
	TMR1CS=1;	// Use external clock
	TMR1ON=1;	// Enable timer 1

	INTCON=0;	// Clear all interrupt bits.
	GIE=1;		// Enable interrupts in general.
	PEIE=1;		// Enable peripheral interrupts in general
	TMR1IE=1;	// Enable timer1 interrupt specifically

	// Make the very first interrupt take 1 second instead of 2
	TMR1H=(32768 >> 8);

	// Loop forever.  
	while(1)
		SLEEP();
}  

