/**
 * Shows operation of the PWM module.
 *
 * Sets up the PWM module to produce output at about 300Hz on pin B3.
 * Meanwhile, timer0 interrupts periodically fire, altering
 * the value of the CCPR1L register and hence altering the
 * duty cycle of the resulting waveform from 0.01%, up to
 * 99.9%, and back down to 0.01% .
 *
 * If you hook a LED up to this pin, it should seem to dim and fade.
 */

#define __16f628a
#include "pic16f628a.h"
#include "tsmtypes.h"
#include "tsmserial.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;

static Uint8 dir;

static void Intr(void) interrupt 0
{
	if(T0IF)	// Did we get a timer0 interrupt?
	{
		T0IF=0;

		if(dir)	// count up
		{
			CCPR1L++;
			if(CCPR1L == 0xff)
				dir=0;
		}
		else
		{
			CCPR1L--;
			if(CCPR1L == 0x00)
				dir=1;
		}
	}
}

void main(void)
{
	dir=0;
#ifdef __16f628a	// Only compile this section for PIC16f628a
	CMCON = 0x07;	/** Disable comparators.  NEEDED FOR NORMAL PORTA
			 *  BEHAVIOR ON PIC16f628a!
			 */
#endif
	TRISB = 0xf7;	// Set port B as all inputs except B3
        TRISA = 0xff;	// Set PORTA as all inputs

	PR2=0xff;	// Set PWM period
	CCPR1L=0x80;	// Set PWM duty cycle
	CCP1CON=0x04|0x08;	// Set PWM mode
	CCP1X=1;	// Set one of the LSB bits.
			// It took me a while to realize the point of 
			// these since they're so inconvenient to use.
			// Set one but only one of these, and your PWM
			// output will never be able to stall -- values 
			// of 0 won't disable it, values of 255 won't pin it.

	T2CON=0x00;
	T2CKPS0=1;	// Set timer 2 prescaler to 1:16.
	T2CKPS1=1;	// These bits are in T2CON.
	TMR2ON=1;	// Enable timer 2.


	// Set up timer0 interrupt
	T0CS=0;	// Internal clock source
	PSA=0;	// Assign prescaler to timer0
	PS2=0;	PS1=1;	PS0=0;
	INTCON=0;
	GIE=1;
	T0IE=1;
	TMR0=0;

	while(1);	// Loop forever
}


