#include	<htc.h>

/*
	The code allows you to use all four PWM channels of the PIC16f690 seperately.
	You can turn on one, two, three or four channels at the same time.

	NOTES: 
	Use registers STRA, STRB, STRC, STRD to turn on/off each of the 4 channels
	STRA = pin5
	STRB = pin6
	STRC = pin7
	STRD = pin14!

	Cycle the CCPR1L register between 0 (0% duty cycle) and 0xff (99.99% duty cycle)
	If you want 100% duty cycle, you must set DC1B0 and DC1B1 to 1
*/
#ifndef _XTAL_FREQ
 // Unless specified elsewhere, 500kHz system frequency is assumed
 #define _XTAL_FREQ 500000
#endif

#define LEDA 1
#define LEDB 2
#define LEDC 4
#define LEDD 8


/** A crappy delay function, doesn't work so nicely. */
void delay(unsigned int us)
{
	unsigned int j;
	for (j = 0; j < us; j++);		
}

/** 
	Basically all this function does is increases CCPR1L from 0 to 0x88 (See how it looks if it goes up to 0xff).
	Then it decreases CCPR1L from 0x88 to 0.

	Use "1" for values of speed, duration, ontime and offtime, and then work from there.
	speed : How quickly the duty cycle increases/decreases. - increasing speed decreases resolution.
	duration: How long each particular duty cycle is held. 
	ontime: How long the LED must stay on after it has reached maximum duty cycle.
	offtime: How long the LED must stay off after it has reached 0 duty cycle at the end.
	LEDs: Use the format LEDA | LEDB | LEDC to pulse specific LEDs.
*/



char pulse(unsigned int speed, unsigned int duration, unsigned int ontime, unsigned int offtime, char LEDs)
{
	int c = speed;
	int i;

	// Decide which channels to turn on according to LEDs
	STRA = ((LEDs & LEDA) != 0);
	STRB = ((LEDs & LEDB) != 0);
	STRC = ((LEDs & LEDC) != 0);
	STRD = ((LEDs & LEDD) != 0);
	
	/** Note: DC1B0 and DC1B1 is the least significant bits of the duty cycle. */
	/* You can just remove any code with DC1B0 and DC1B1 if you want. but then you will have less resolution */
	DC1B0 = 0;
	DC1B1 = 0;
	CCPR1L = c;	
	delay(duration);
	while (CCPR1L > 0) {
		if (c > 0) {
			DC1B0 = 0;
			DC1B1 = 0;
		} else {
			DC1B1 = 1;
			DC1B0 = 1;
		}
		delay(duration);
		CCPR1L = CCPR1L + c;
		if (c > 0) {		
			DC1B0 = 1;
			delay(duration);
			DC1B0 = 0;
			DC1B1 = 1;
			delay(duration);
			DC1B0 = 1;
			delay(duration);
		} else {
			DC1B0 = 0;
			delay(duration);
			DC1B0 = 1;
			DC1B1 = 0;
			delay(duration);
			DC1B0 = 0;
			delay(duration);
		}
		if (CCPR1L >= 0x88) // I found that going up only to 0x88 works nicer, you can change this to 0xff.
		{
			c = -c;
			delay(ontime*1000);
		}
		if (CCPR1L <= 0)
		{
			delay(offtime*1000);
		}
		delay(duration);	
	}
}


int main(void)
{
    /** Set up chip clock speed */
	IRCF0 = 1;
	IRCF1 = 1;
	IRCF2 = 0;
	OSTS = 0;
	SCS = 1;
	/* Set up output ports */
	TRISC = 0;		/* all bits output */
	/* Set up PWM frequency and timer */
	PR2 = 0b10000001;
	T2CON = 0b00000111;
	
	/* use pulse steering with single output mode */
	CCP1CON = 0b00001100;

	while(1) 
	{
		pulse(1, 1, 1, 1, LEDA | LEDC); 
		pulse(1, 1, 1, 1, LEDD | LEDB); 
	}
}